.net XSL排序问题

.net XSL排序问题,.net,xml,xslt,xslcompiledtransform,.net,Xml,Xslt,Xslcompiledtransform,我在尝试使用CLR4.0中的XslCompiledTransform对XSL文件进行排序时遇到问题。这是我的示例XML文件(注意:第二个元素后面有一个空格): 我没有试图重现这个问题,也没有发现XSL有任何明显的错误。下面是我将探讨的问题,看看这是您的问题还是XSL引擎中的错误:尝试删除之后的空格,并将id“a”更改为“C”。您是否按“B”、“C”的顺序获得输出?换句话说,确保它实际上是按id排序的。如果每个api元素的XML修改为以下内容,结果将按预期排序: <api id="apiId

我在尝试使用CLR4.0中的XslCompiledTransform对XSL文件进行排序时遇到问题。这是我的示例XML文件(注意:第二个
元素后面有一个空格):


我没有试图重现这个问题,也没有发现XSL有任何明显的错误。下面是我将探讨的问题,看看这是您的问题还是XSL引擎中的错误:尝试删除
之后的空格,并将id“a”更改为“C”。您是否按“B”、“C”的顺序获得输出?换句话说,确保它实际上是按id排序的。

如果每个
api
元素的XML修改为以下内容,结果将按预期排序:

<api id="apiId">
   <id>apiId</id>
   <foos>
      <foo />
   </foo>       
</api>
b)只有XSL文件中对
@id
的第二个引用更改为
id
,结果仍将按字母顺序排序


xslcomiledtransform
可能试图在名为
id
的子元素而不是名为
id
的属性上进行排序,或者这可能是愚蠢的运气。不管怎样,我已经验证了它是否愿意在名为
id
的子元素上正确排序

考虑到这一点,我可以想出两种变通方法,但这两种方法都要求您对转换过程有一定程度的控制

方法1:您可以更改XML

更改编写原始XML的过程,将
id
指定为
api
元素包含的第一个元素。然后更新XSL,将对
@id
的引用替换为
id

方法2:您可以在应用XSL之前预处理XML

使用XSL转换将
id
属性的值移动到
api
的子元素中,然后对中间XML文档应用与方法1中相同的XSL。在处理大型XML文件时,两次转换文档显然不太理想

以下XSL将使您从原始XML转换为中间XML:

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.1">  
   <!-- recursively copy each element (including root) -->
   <xsl:template match="*|/">
      <xsl:copy>      
         <!-- xsl:copy ignores attributes, copy those as well -->
         <xsl:copy-of select="@*"/>      
         <!-- continue to deep copy the element -->
         <xsl:apply-templates />      
      </xsl:copy>
   </xsl:template>    
   <!-- for api elements, move the id attribute into an element -->
   <xsl:template match="api">
      <api>
         <id>
            <xsl:value-of select="@id"/>
         </id>      
         <!-- continue deep copy of api element contents -->
         <xsl:apply-templates />
      </api>
   </xsl:template>   
</xsl:stylesheet>


我希望这有帮助

@Russ Ferri,谢谢你的回答。它为我指明了正确的方向。XslCompiledTransform中的错误似乎在于,当您想按元素的属性排序时,它实际上是按该元素的第一个子元素的值排序的。正如Russ指出的,这将与我的原始转换文件正确排序:

<reflection>
  <apis>
    <api id="C">
      <id>C</id>
      <foos>
        <foo/>
      </foos>
    </api>
    <api id="B">
      <id>B</id>
      <foos>
        <foo/>
      </foos>
    </api>
  </apis>
</reflection>

C
B
但这也将:

<reflection>
  <apis>
    <api id="C">
      <anyElementName>C</anyElementName>
      <foos>
        <foo/>
      </foos>
    </api>
    <api id="B">
      <anyElementName>B</anyElementName>
      <foos>
        <foo/>
      </foos>
    </api>
  </apis>
</reflection>

C
B
事实上,属性名称完全被忽略,因此,如果我对以下内容运行转换:

<reflection>
  <apis>
    <api id="C">
      <anyElementName>Z</anyElementName>
      <foos>
        <foo/>
      </foos>
    </api>
    <api id="A">
      <anyElementName>Y</anyElementName>
      <foos>
        <foo/>
      </foos>
    </api>
    <api id="B">
      <anyElementName>X</anyElementName>
      <foos>
        <foo/>
      </foos>
    </api>
  </apis>
</reflection>
<html>
  <body>
    <table>
      <tr>
        <td>B</td>
      </tr>
      <tr>
        <td>A</td>
      </tr>
      <tr>
        <td>C</td>
      </tr>
    </table>
  </body>
</html>

Z
Y
X
结果如下所示:

<reflection>
  <apis>
    <api id="C">
      <anyElementName>Z</anyElementName>
      <foos>
        <foo/>
      </foos>
    </api>
    <api id="A">
      <anyElementName>Y</anyElementName>
      <foos>
        <foo/>
      </foos>
    </api>
    <api id="B">
      <anyElementName>X</anyElementName>
      <foos>
        <foo/>
      </foos>
    </api>
  </apis>
</reflection>
<html>
  <body>
    <table>
      <tr>
        <td>B</td>
      </tr>
      <tr>
        <td>A</td>
      </tr>
      <tr>
        <td>C</td>
      </tr>
    </table>
  </body>
</html>

B
A.
C

如果按
元素排序,哪一个是正确的排序?如果将sytyle sheet版本更改为'1.0'(任何内容)>=2.0

好的问题,它会起作用。它们应该作为评论而不是答案提交。谢谢您的反馈,@Mads。我将其重新表述为如何调试问题的建议。当我将“a”改为“C”时,排序顺序显示为空格正确,空格不正确,因此它真的没有任何意义。你再现了这个问题吗?如果你没有,请想想其他有类似(但真实)问题的人,他们可能会对你的答案感到困惑。好吧,@Alejandro,我澄清说我没有重现这个问题,这只是一个调试建议。它看起来有效,但实际上是阻止所有排序。当我将“A”改为“C”(这会将初始元素按未排序的顺序排列)并去掉空格时,结果文件的顺序从未改变过,无论是否有空格。你是对的,对此表示抱歉。在进一步研究这个问题之后,我将用我注意到的一些东西更新这个答案。这个问题似乎不可重现(用MSXSL 4和3测试)。如果
xslcomiledtransform
中有bug,这应该是一个
xsltprocessor
标记的问题。如果有人想跟踪它,我也将此提交给了Microsoft。我使用了稍有不同的文件内容,但结果是一样的:我努力了,但无法重新编写!!!
<reflection>
  <apis>
    <api id="C">
      <anyElementName>C</anyElementName>
      <foos>
        <foo/>
      </foos>
    </api>
    <api id="B">
      <anyElementName>B</anyElementName>
      <foos>
        <foo/>
      </foos>
    </api>
  </apis>
</reflection>
<reflection>
  <apis>
    <api id="C">
      <anyElementName>Z</anyElementName>
      <foos>
        <foo/>
      </foos>
    </api>
    <api id="A">
      <anyElementName>Y</anyElementName>
      <foos>
        <foo/>
      </foos>
    </api>
    <api id="B">
      <anyElementName>X</anyElementName>
      <foos>
        <foo/>
      </foos>
    </api>
  </apis>
</reflection>
<html>
  <body>
    <table>
      <tr>
        <td>B</td>
      </tr>
      <tr>
        <td>A</td>
      </tr>
      <tr>
        <td>C</td>
      </tr>
    </table>
  </body>
</html>