Here is my code:
XElement transformed = new XElement("stuff");
using (XmlWriter writer = transformed.CreateWriter())
{
_xslt.Transform(section.CreateReader(), writer);
}
where _xslt
is a XslCompiledTransform
and section
is an XElement
.
After the transform, the writer has content where the < has changed to <
. This is not an issue with the xsl because if I use an XmlWriter that saves to a file, I do NOT see this escaping. The xsl has a few <xsl:value-of ... disable-output-escaping="yes">
transforms and those are the ones causing an issue. Again, if I write the transform to a file, there is not a problem. Thought I might need to change some of the settings for the writer, but XElement.CreateWriter
does not have a constructor that takes an XmlWriterSettings
.
Is there a way to do this without transforming to a string or stringbuilder and then reparsing back into XElement?
New Info
Instead of the XmlWriter, I changed my code to:
using (StreamWriter writer = new StreamWriter())
{
_xslt.Transform(section.CreateReader(), null, writer);
}
The StreamWriter has non-escaped characters like I want, now, how do I get that loaded back into my XElement?
Request for more info
Here's the xsl that works fine with a StreamWriter, but not with an XmlWriter:
<xsl:template match="processing-instruction(mark_start')">
<xsl:text disable-output-escaping="yes"><addtext></xsl:text>
</xsl:template>
<xsl:template match="processing-instruction('mark_end')">
<xsl:text disable-output-escaping="yes"></addtext></xsl:text>
</xsl:template>
And no, I have no control over the xml so I am stuck with the processing instructions as given. In summary, the DOE works with StreamWriter but not XmlWriter.
Request for Sample XML
Here is what the xml looks like that I'm processing:
<text>
this is some text
<?mark_start&g开发者_StackOverflow中文版t;
and some new text
<?mark_end>
and the rest of the text
</text>
Well, your basic problem is that you are abusing the XSLT language by trying to write tags rather than writing nodes. Outputting a start tag from one template and the corresponding end tag from another is not the way XSLT is designed to be used. It looks as if you are processing some kind of "overlap markup" in the source document; doing this properly is a complex subject with an extensive literature. Resorting to writing tags using disable-output-escaping is tempting, but you need to understand (as your experiments demonstrate) that it will only work when the XSLT processor is writing serialized lexical XML as its output, and you will then need to re-parse that XML to make it available for the next stage of processing.
Until someone shows me something better:
using (MemoryStream stream = new MemoryStream())
{
using (StreamWriter writer = new StreamWriter(stream))
{
_xslt.Transform(section.CreateReader(), null, writer);
stream.Seek(0, SeekOrigin.Begin);
transformed = XElement.Load(stream);
}
}
This stylesheet:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()[1]|@*"/>
</xsl:copy>
<xsl:apply-templates select="following-sibling::node()[1]"/>
</xsl:template>
<xsl:template match="processing-instruction('mark_start')">
<addtext>
<xsl:apply-templates select="following-sibling::node()[1]"/>
</addtext>
<xsl:apply-templates
select="following-sibling::processing-instruction('mark_end')
/following-sibling::node()[1]"/>
</xsl:template>
<xsl:template match="processing-instruction('mark_end')"/>
</xsl:stylesheet>
Output:
<text>
this is some text
<addtext>
and some new text
</addtext>
and the rest of the text
</text>
Note: Fine grained traversal.
精彩评论