XSLT复制和排序转换在XslCompiledTransform中抛出异常

时间:2017-11-17 11:56:37

标签: c# xml sorting xslt

我有一个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>

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

  

在添加了text,comment,pi或子元素节点之后,无法将属性和命名空间节点添加到父元素。

我在我的XSLT上尝试了很多变化,但它们要么没有产生输出,要么甚至没有有效的XSLT!

我的目标是否可以实现,如果XSLT能达到我想要的效果呢?

1 个答案:

答案 0 :(得分: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"通常是一个更好的主意,否则您将获得向前兼容的处理,这可能不会提醒您使用不受支持的功能。