2010-11-15 40 views
1

我在尝试使用XSLT对XML文档进行排序,并希望保留注释。迄今为止这么好,因为这个问题已经有了一些答案(见相关..)。 但是!没有这些(优秀)答案涉及到一个XML看起来像这样:现在会发生什么使用XSLT对XML进行排序,同时保留多条评论

<xml> 
    <beatles> 
     <!-- comment(1): john is actually my favourite --> 
     <!-- comment(2): John died tragically in 1980 --> 
     <beatle name="John"/> 

     <beatle name="Ringo"/> 

     <beatle name="George"/> 

     <!-- comment(1): Paul still does live concerts to this day --> 
     <!-- comment(2): contrary to common folklore, Paul is NOT dead! --> 
     <beatle name="Paul"/> 
    </beatles> 
</xml> 

?我想以按名称排序甲壳虫(上帝保佑他们),并保持各甲壳虫的所有意见的地方,为了得到这样的结果:

<xml> 
    <beatles> 
     <beatle name="George"/> 

     <!-- comment(1): john is actually my favourite --> 
     <!-- comment(2): John died tragically in 1980 --> 
     <beatle name="John"/> 

     <!-- comment(1): Paul still does live concerts to this day --> 
     <!-- comment(2): contrary to common folklore, Paul is NOT dead! --> 
     <beatle name="Paul"/> 

     <beatle name="Ringo"/> 
    </beatles> 
</xml> 

好老前同辈::评论( )[1]在这里不起作用。在常规代码中,我只是对所有前面的注释做一个反向循环,当我点击一个非注释节点时停止;但众所周知,XSLT的不能逃脱。

有什么想法?

TIA!

DF。

+0

好问题,+1。我认为@ Tim-C给了你一个完美的答案。 – 2010-11-15 13:12:04

回答

0

当复制相应的beatle节点时,您还应该应用其注释。这就是你需要做的。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:template match="/"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*|node()"/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="beatles"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*"/> 
      <xsl:apply-templates select="beatle"> 
       <xsl:sort select="@name" data-type="text"/> 
      </xsl:apply-templates> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="beatle"> 
     <xsl:variable name="current" select="."/> 
     <xsl:apply-templates 
       select="preceding-sibling::comment()[generate-id(following-sibling::beatle[1]) = generate-id($current)]"/> 
     <xsl:copy> 
      <xsl:apply-templates select="@*|node()"/> 
     </xsl:copy> 
    </xsl:template> 


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

输出:

<?xml version="1.0" encoding="windows-1251"?> 
<xml> 
    <beatles> 
     <beatle name="George"/> 
     <!-- comment(1): john is actually my favourite --> 
     <!-- comment(2): John died tragically in 1980 --> 
     <beatle name="John"/> 
     <!-- comment(1): Paul still does live concerts to this day --> 
     <!-- comment(2): contrary to common folklore, Paul is NOT dead! --> 
     <beatle name="Paul"/> 
     <beatle name="Ringo"/> 
    </beatles> 
</xml> 
+0

这是我会采取的方法,但如果有11,000披头士,它将开始表现不佳。 – 2010-11-15 19:28:28

+0

好的形式,每个人!我最终使用了@Alex Nikolaenkov的解决方案,因为我的问题比订购相同的节点要复杂一点 - 我有几个不同的节点,并且必须订购节点类型组,因此Alex提供的解决方案更合适。 @ Tim-C - 谢谢你的回答,因为我学到了更多关于XSLT的知识(我昨天才开始学习)。再次感谢所有! – deebugger 2010-11-15 19:31:46

+0

@罗伯特罗斯尼 - 可能是这样,但我的问题并没有涉及那么多的节点,所以我很高兴地使用它.. – deebugger 2010-11-15 19:33:30

1

,我认为这可以通过其中列出了一个给定的“披头士”元素的所有意见的一个关键的手段来实现。

<xsl:key name="comments" match="comment()" use="following-sibling::beatle[1]/@name" /> 

因此,对于每个评论,它都由第一个连续的beatle元素索引。

然后,您可以按如下方式使用它来列出任何beatle元素的所有注释。

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
    <xsl:output method="xml"/> 

    <xsl:key name="comments" match="comment()" use="following-sibling::beatle[1]/@name" /> 

    <xsl:template match="/xml/beatles"> 
     <beatles> 
     <xsl:for-each select="beatle"> 
      <xsl:sort select="@name" /> 

      <!-- Loop through all comments for the beatle element --> 
      <xsl:for-each select="key('comments', @name)"> 
       <xsl:comment> 
        <xsl:value-of select="." /> 
       </xsl:comment> 
      </xsl:for-each> 

      <!-- Copy the beatle element --> 
      <xsl:copy> 
       <xsl:copy-of select="@*" /> 
      </xsl:copy> 
     </xsl:for-each> 
     </beatles> 
    </xsl:template> 

</xsl:stylesheet> 
+0

为这样一个简单的任务使用密钥的IMO是一个矫枉过正。顺便说一下,当使用命令式XSLT时,你会得到更紧密的耦合,并且这些代码的修改会随着时间变得越来越难。 – 2010-11-15 09:16:39

+0

+1为一个完美的答案! – 2010-11-15 13:09:12

+0

@ Alex-Nikolaenkov:钥匙是正确的情况下的正确工具 - 而且*这种情况是使用钥匙的最佳选择。 – 2010-11-15 13:10:23