【问题标题】:Xslt transform in .net without escaping <.net 中的 Xslt 转换而不转义 <
【发布时间】:2011-06-16 04:15:49
【问题描述】:

这是我的代码:

XElement transformed = new XElement("stuff");
using (XmlWriter writer = transformed.CreateWriter())
{
  _xslt.Transform(section.CreateReader(), writer);
}

其中_xsltXslCompiledTransformsectionXElement。 转换后,作者的内容中 &lt;。这不是 xsl 的问题,因为如果我使用保存到文件的 XmlWriter,我看不到这种转义。 xsl 有几个&lt;xsl:value-of ... disable-output-escaping="yes"&gt; 转换,这些是导致问题的。同样,如果我将转换写入文件,则没有问题。以为我可能需要更改编写器的一些设置,但XElement.CreateWriter 没有采用XmlWriterSettings 的构造函数。

有没有办法做到这一点,而无需转换为字符串或字符串生成器,然后重新解析回 XElement?

新信息

我将代码改为:而不是 XmlWriter:

using (StreamWriter writer = new StreamWriter())
{
  _xslt.Transform(section.CreateReader(), null, writer);
}

StreamWriter 具有我想要的非转义字符,现在,如何将其加载回我的 XElement?

索取更多信息

以下是适用于 StreamWriter 的 xsl,但不适用于 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>

不,我无法控制 xml,所以我坚持使用给定的处理指令。总之,DOE 可以使用 StreamWriter,但不能使用 XmlWriter。

请求样本 XML

这是我正在处理的 xml 的样子:

<text>
    this is some text
    <?mark_start>
    and some new text
    <?mark_end>
    and the rest of the text
</text>

【问题讨论】:

  • 请显示您正在转换的部分 XML,以及转换后的 XML。
  • 我在上面添加了更多信息。
  • @Wave: 请发布错误的 XML
  • @JS:正如我在问题中提到的,我得到了 <而不是
  • @Wave: 为什么不发布 XML 让我们看看发生了什么?为什么要让我们猜测?

标签: xml character-encoding xslt


【解决方案1】:

这个样式表:

<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>

输出:

<text>
    this is some text
    <addtext>
    and some new text
    </addtext>
    and the rest of the text
</text>

注意:细粒度遍历。

【讨论】:

  • 我谦虚地纠正。我想我必须将您的解决方案的复杂性与我提出的 memorystream/streamwriter 解决方案的复杂性进行比较。谢谢你的回答。
【解决方案2】:

直到有人向我展示更好的东西:

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

【讨论】:

    【解决方案3】:

    嗯,您的基本问题是您通过尝试编写标签而不是编写节点来滥用 XSLT 语言。从一个模板输出开始标记并从另一个模板输出相应的结束标记并不是 XSLT 的设计使用方式。看起来好像您正在源文档中处理某种“重叠标记”;正确地做到这一点是一个具有广泛文献的复杂主题。使用 disable-output-escaping 编写标签很诱人,但您需要了解(正如您的实验所证明的那样)它仅在 XSLT 处理器编写序列化词法 XML 作为其输出时才有效,然后您需要重新解析该 XML 以使其可用于下一阶段的处理。

    【讨论】:

    • 我同意我在滥用 xslt :) 但是,我被作为输入提供的 xml 滥用了!!你是对的,因为我试图用一个 PI 启动一个节点,然后用另一个 PI 结束它,以尝试获取给定的 xml 并将其变成结构更好的东西。我在上面发布的答案至少可以完成工作,但我非常感谢学习“重叠标记”的指针。
    猜你喜欢
    • 1970-01-01
    • 2015-12-01
    • 2011-02-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-07
    相关资源
    最近更新 更多