Wavel
Wavel

Reputation: 966

Xslt transform in .net without escaping <

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 &lt;. 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">&lt;addtext></xsl:text>
</xsl:template>

<xsl:template match="processing-instruction('mark_end')">
    <xsl:text disable-output-escaping="yes">&lt;/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>
    and some new text
    <?mark_end>
    and the rest of the text
</text>

Upvotes: 0

Views: 447

Answers (3)

user357812
user357812

Reputation:

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.

Upvotes: 0

Wavel
Wavel

Reputation: 966

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);
    }
}

Upvotes: 0

Michael Kay
Michael Kay

Reputation: 163595

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.

Upvotes: 1

Related Questions