Reputation: 1816
I have one XML where some raw values are present as nodeset. i want to make it as variable and use in further process. Please look into below stuff:
XML:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<element1>Some value in the element1</element1>
<element2 value="<sno>1</sno><name>Amrendra</name><mobile>0123456789</mobile>"></element2>
</root>
XSLT:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output indent="yes"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:variable name="element">
<root>
<xsl:value-of select="/root/element2/@value" disable-output-escaping="yes"/>
</root>
</xsl:variable>
<xsl:template match="/">
<root>
<applytemp>
<xsl:apply-templates select="$element/root/name"/>
</applytemp>
<copy-of>
<xsl:copy-of select="$element/root/name"/>
</copy-of>
<value-of>
<xsl:value-of select="$element/root/name"/>
</value-of>
</root>
</xsl:template>
</xsl:stylesheet>
CURRENT OUT:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<applytemp/>
<copy-of/>
<value-of/>
</root>
REQUIRED OUT:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<applytemp>Amrendra</applytemp>
<copy-of>Amrendra</copy-of>
<value-of>Amrendra</value-of>
</root>
Upvotes: 0
Views: 734
Reputation: 163262
Using disable-output-escaping when writing to a variable is a long-standing source of problems and controversy, known within the XSL WG as the "sticky-doe" problem. The XSLT 1.0 spec says (in §16.4)
it is also an error to convert a result tree fragment to a number or a string if the result tree fragment contains a text node for which escaping was disabled.
But Erratum E2 says:
When a root node is copied using an xsl:copy-of element (see [11.3 Using Values of Variables and Parameters with xsl:copy-of]) and escaping was disabled for a text node descendant of that root node, then escaping should also be disabled for the resulting copy of that text node. For example
<xsl:variable name="x">
<xsl:text disable-output-escaping="yes"><</xsl:text>
</xsl:variable>
<xsl:copy-of select="$x"/>
should output <
not <
.
That is, the disable-output-escaping property is "sticky": it survives in the variable and re-emerges when the copy is done.
This was reverted in XSLT 2.0: see appendix J.1.4, item 20:
An erratum to XSLT 1.0 specified what has become known as "sticky disable-output-escaping": specifically, that it should be possible to use disable-output-escaping when writing a node to a temporary tree, and that this information would be retained for use when the same node was later copied to a final result tree and serialized. XSLT 2.0 no longer specifies this behavior (though it permits it, at the discretion of the implementation).
Given this variation between specs, it's not going to be very predictable what a particular processor actually does in this situation. But then, it's always best to steer well clear of disable-output-escaping.
Upvotes: 0
Reputation: 116959
I have one XML where some raw values are present as nodeset.
No, what you have is an escaped XML fragment represented as a string. Your attempt to unescape it using disable-output-escaping
cannot work, because disable-output-escaping
is performed only when writing to the output.
If your processor support XPath/XSLT 3.0, you can use the parse-xml-fragment()
function to convert the string to a node tree:
XSLT 3.0
<xsl:stylesheet version="3.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:variable name="elem2" select="parse-xml-fragment(/root/element2/@value)" />
<!-- identity transform -->
<xsl:mode on-no-match="shallow-copy"/>
<xsl:template match="/">
<root>
<applytemp>
<xsl:apply-templates select="$elem2/name"/>
</applytemp>
<copy-of>
<xsl:copy-of select="$elem2/name"/>
</copy-of>
<value-of>
<xsl:value-of select="$elem2/name"/>
</value-of>
</root>
</xsl:template>
</xsl:stylesheet>
Result
<?xml version="1.0" encoding="UTF-8"?>
<root>
<applytemp>
<name>Amrendra</name>
</applytemp>
<copy-of>
<name>Amrendra</name>
</copy-of>
<value-of>Amrendra</value-of>
</root>
Demo: https://xsltfiddle.liberty-development.net/ejivdH2/2
In earlier versions you need to do this in two passes. First, unescape the string using disable-output-escaping
and save the result to a file. Then process the resulting file.
Upvotes: 1
Reputation: 3435
change your variable declaration as below
<xsl:variable name="element">
<root>
<xsl:analyze-string select="//root/element2/@value" regex="<([a-z]+)>(.*?)</\1>">
<xsl:matching-substring>
<xsl:element name="{regex-group(1)}"><xsl:value-of select="regex-group(2)"/></xsl:element>
</xsl:matching-substring>
</xsl:analyze-string>
</root>
</xsl:variable>
Output
<root>
<applytemp>
<name>Amrendra</name>
</applytemp>
<copy-of>
<name>Amrendra</name>
</copy-of>
<value-of>Amrendra</value-of>
</root>
See transformation at https://xsltfiddle.liberty-development.net/bFWR5DZ
Upvotes: 1