简体   繁体   中英

How to include CDATA when writing Saxon's XdmNode to Stream in C#

I have an XdmNode object generated by a transform that I need to write to a stream that includes some CDATA, but I cannot get the output to include the CDATA escaping.

Is this because I'm not going through the process of serialization, eg, using the Serializer class? If so, how do I do this? I can see the Serializer class has a serializeNode() method in Java, but not in C#... only the transform/etc seem to be able to "use" it. Or is this a problem around the cdata-section-elements statement?

Using the XML and XSLT from here to illustrate: How do I force xslt transformation to load data into cdata sections?

This uses .NET 4.5 with Saxon 9.6.0.6 in C#.

C# code:

Processor processor = new Processor();
XdmNode node = GetNode(processor);  //gets XdmNode for XML doc below
XsltTransformer transformer = GetTransformer(processor);  //gets transform below

transformer.InitialContextNode = node;
XdmDestination output = new XdmDestination();
transformer.Run(output);
string results = output.XdmNode.OuterXml;

using (XmlWriter writer = XmlWriter.Create(Console.Out))
{
    output.XdmNode.WriteTo(writer);
}

XSLT:

<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"
  cdata-section-elements="num"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="node()|@*">
     <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
     </xsl:copy>
 </xsl:template>
</xsl:stylesheet>

XML:

<nums>
  <num>01</num>
  <num>02</num>
  <num>03</num>
  <num>04</num>
  <num>05</num>
  <num>06</num>
  <num>07</num>
  <num>08</num>
  <num>09</num>
  <num>10</num>
</nums>

Expected output:

<nums>
   <num><![CDATA[01]]></num>
   <num><![CDATA[02]]></num>
   <num><![CDATA[03]]></num>
   <num><![CDATA[04]]></num>
   <num><![CDATA[05]]></num>
   <num><![CDATA[06]]></num>
   <num><![CDATA[07]]></num>
   <num><![CDATA[08]]></num>
   <num><![CDATA[09]]></num>
   <num><![CDATA[10]]></num>
</nums>

Actual output (both on the console and in the string):

<nums>
    <num>01</num>
    <num>02</num>
    <num>03</num>
    <num>04</num>
    <num>05</num>
    <num>06</num>
    <num>07</num>
    <num>08</num>
    <num>09</num>
    <num>10</num>
</nums>

It seems that what you want to do is to send an XdmNode to a Serializer to have it serialized with the properties that are set on the Serializer. The easiest way to do this is probably to run a dummy query:

QueryCompiler qc = Processor.NewQueryCompiler();
QueryEvaluator qe = qc.Compile(".").Load();
qe.ContextItem = xdmNode;
qe.Run(serializer);

The XQuery expression "." simply returns the context item.

Incidentally, the API documentation for Serializer doesn't say what form the CDATA_SECTION_ELEMENTS property should take, but I think it is probably a whitespace separated sequence of QNames in Clark notation, that is Q{uri}local . Or just the local name if there are no namespaces.

(This is similar to the approach often used in the Java JAXP interface of running an "identity transformation". But an identity query is much simpler.)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM