How can I convert the following XML to an escaped text using XSLT?
Source:
<?xml version="1.0" encoding="utf-8"?>
<abc>
<def ghi="jkl">
mnop
</def>
</abc>
Output:
<TestElement><?xml version="1.0" encoding="utf-8"?><abc><def ghi="jkl">
mnop
</def></abc></TestElement>
Currently, I'm trying the following XSLT and it doesn't seem to work properly:
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" encoding="utf-8" />
<xsl:template match="/">
<xsl:variable name="testVar">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:variable>
<TestElement>
<xsl:value-of select="$testVar"/>
</TestElement>
</xsl:template>
</xsl:stylesheet>
Output of XSLT statement by the .NET XslCompiledTransform comes out as the following:
<?xml version="1.0" encoding="utf-8"?><TestElement>
mnop
</TestElement>
Why can't you just run
Do you need to use XSLT? Because, for reasons explained by Pavel Minaev, it would be much simpler to use another tool. An example with xmlstartlet:
Your code works the way it does because
xsl:value-of
retrieves the string-value of the node set.To do what you want, I'm afraid that you'll have to code it explicitly:
Note that this solution ignores comment nodes, and inserts unneccessary namespace nodes (as
namespace::
axis will include all nodes inherited from parent). Regarding namespaces, however, the resulting quoted XML will be semantically equivalent to the example that you provided in your reply (since those repeated redeclarations don't really change anything).Also, this won't escape the
<?xml ... ?>
declaration, simply because it is not present in XPath 1.0 data model (it's not a processing instruction). If you actually need it in the output, you'll have to insert it manually (and make sure that encoding it specifies is consistent with serialization encoding of your XSLT processor).Anyone who is concerned about licensing ambiguity when reusing code snippets from stack overflow may be interested in the following 3-clause BSD-licensed code, which appears to do what is requested by the original poster:
http://lenzconsulting.com/xml-to-string/
instead of escaping you can add the text inside a CDATA section. Text inside a CDATA section will be ignored by the parser, similar to if it was escaped.
your example would look like this
using following XSLT snippet:
If you have access to it, I would recommend the Saxon extention serialize. It does exactly what you want it to do. If you don't want to do that, you'd have to manually insert the entity references as you build the document. It'd be brittle, but it would work for most documents:
Most notably, this will probably break if your attributes have the double-quote character. It's really better to use saxon, or to use a user-written extention that uses a proper serializer if you can't.