【问题标题】:XSLT copy and sort transform throwing exception in XslCompiledTransformXslCompiledTransform 中的 XSLT 复制和排序转换引发异常
【发布时间】:2018-05-01 04:47:56
【问题描述】:

我有一个 XSLT 转换,它应该按名称进行复制和排序 - 因此不会丢失任何内容,但输出按字母顺序排序。 我正在使用 XslCompiledTransform.Transform 方法在 C# 中执行此操作。

示例输入:

<root>
    <test val="1"/>
    <alpha val="2"/>
    <gamma Order="C">
        <aSubGamma val="3"/>
        <cSubGamma val="4"/>
        <bSubGamma val="5"/>
    </gamma>
    <gamma Order="B">
        <aSubGamma val="6"/>
        <cSubGamma val="7"/>
        <bSubGamma val="8"/>
    </gamma>
    <beta val="9"/>
</root>

我想在输出中得到什么:

<root>
    <alpha val="2"/>
    <beta val="9"/>
    <gamma Order="B">
        <aSubGamma val="6"/>
        <bSubGamma val="8"/>
        <cSubGamma val="7"/>
    </gamma>
    <gamma Order="C">
        <aSubGamma val="3"/>
        <bSubGamma val="5"/>
        <cSubGamma val="4"/>
    </gamma>
    <test val="1"/>
</root>

到目前为止,我的 XSLT 非常简单而且有些正确:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
      <xsl:template match="node()|@*">
    <xsl:copy>
      <xsl:apply-templates select="node()|@*">
        <xsl:sort select="name()"/>
      </xsl:apply-templates>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

如果我在已删除gamma 元素上的Order 属性的XML 上使用它,一切都很好。 但是,有了这些属性,我得到以下异常:

在文本、注释、pi 或子元素节点已添加后,不能将属性和命名空间节点添加到父元素。

我在我的 XSLT 上尝试了许多变体,但它们要么不产生输出,要么甚至不是有效的 XSLT!

我的目标可以实现吗?如果是这样,XSLT 会达到我想要的结果吗?

【问题讨论】:

    标签: c# xml sorting xslt


    【解决方案1】:

    不要一起处理属性和子节点,所以改

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

    <xsl:template match="*">
      <xsl:copy>
        <xsl:apply-templates select="@*"/>
        <xsl:apply-templates>
          <xsl:sort select="local-name()"/>
        </xsl:apply-templates>
      </xsl:copy>
    </xsl:template>
    
    <xsl:template match="@* | text() | processing-instruction() | comment()">
      <xsl:copy/>
    </xsl:template>
    

    另请注意,XslCompiledTransform 是一个 XSLT 1 处理器,因此在样式表上使用 version="1.0" 通常是一个更好的主意,否则您将获得向前兼容的处理,这可能不会提醒您使用不受支持的功能。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-07-05
      • 1970-01-01
      • 2011-09-07
      • 2012-11-11
      • 2011-07-13
      • 1970-01-01
      • 2021-01-01
      • 1970-01-01
      相关资源
      最近更新 更多