2010-08-10 72 views
1

所以,我有我的手一个非常混乱的问题..XPath的结果是不正确的 - 通过整个XML不会

它使用XPath时,仿佛整个XML数据的层次结构不被搜索过在XSL中表达。

一些虚设XML数据:

<pets name="myPets" NUM="2"> 
    <dog name="allMyDogs" NUM="5"> 
     <dog name="Frank" NUM="3"/> 
     <dog name="Spot" NUM="4"/> 
     <dog name="Rover" NUM="1"/> 
     <dog name="Rupert" NUM="6"/> 
     <cat name="Lucy" NUM="4"/> 
    </dog> 
    <cat name="allMyCats" NUM="4"> 
     <cat name="Simba" NUM="4"/> 
     <cat name="Princess" NUM="5"/> 
     <cat name="Fluffy" NUM="1"/> 
     <cat name="Lucy" NUM="3"/> 
     <cat name="Lucy" NUM="35"/> 
     <cat name="Lucy" NUM="6"/> 
     <cat name="Lucy" NUM="1"/> 
    </cat> 
    <cat name="Lucy" NUM="9"/> 
</pets> 

以下是我相信是造成问题的的XSLT代码部分:

<xsl:key name="elem_key" match="elem" use="concat(@key, .)" /> 

    <xsl:variable name="all_data"> 
    <xsl:apply-templates select="*"> 
     <xsl:sort select="name()" /> 
    </xsl:apply-templates> 
    </xsl:variable> 

    <xsl:template match="//*[@NUM&lt;=4]"> 
    <elem key="{name()}"> 
     <xsl:copy-of select="@*" /> 
     <xsl:for-each select="@*"> 
     <xsl:sort select="name()" /> 
     <attribute>|<xsl:value-of select="name()" />|</attribute> 
     </xsl:for-each> 
    </elem> 
    </xsl:template> 

    <xsl:template match="/"> 
    <html> 
     <body> 
     <xsl:for-each select="msxsl:node-set($all_data)"> 
       <xsl:for-each select="*[generate-id()=generate-id(key('elem_key',concat(@key, .))[1])]"> 
       <table > 
        <tr> 
        <td>Element Name</td> 
        <xsl:for-each select="*"> 
         <td> 
         <xsl:value-of select="translate(.,'|','')" /> 
         </td> 
        </xsl:for-each> 
        </tr> 
        <xsl:for-each select="key('elem_key', concat(@key, .))"> 
        <xsl:variable name="curr_elem" select="." /> 
        <tr> 
         <td> 
         <xsl:value-of select="@key" /> 
         </td> 
         <xsl:for-each select="*"> 
         <td > 
          <xsl:value-of select="$curr_elem/@*[name()=translate(current(),'|','')]" /> 
         </td> 
         </xsl:for-each> 
        </tr> 
        </xsl:for-each> 
       </table> 
       <p /> 
       </xsl:for-each> 
     </xsl:for-each> 
     </body> 
    </html> 
    </xsl:template> 

中的XPath表达式中使用:

//*[@NUM&lt;=4] 

(以上应该产生许多成果)

不正确的结果我得到:

Element Name name  NUM 
pets   myPets 2 

正如你可以看到它似乎停止在根。

如果我改变XPath来:

//*[@NUM=4] 

我得到这些不正确的结果:

Element Name name NUM 
dog  Spot  4 


Element Name name  NUM 
cat  Lucy  4 


Element Name name  NUM 
cat  allMyCats 4 

事情似乎发生的是,它会停止搜索分解成层次结构一旦找到了比赛。前两个(Spot和Lucy)是正确的,但是当allMyCats(Simba)的子节点的NUM为4时,它停在所有MyCats上。

任何人都可以帮助我修复此代码,以便它返回正确的结果?我很沮丧! :(

谢谢!

+0

没有完整的样式表,我只能猜测...如果var'all_data'被声明为样式表的顶层元素,那么我建议在'xsl:apply-templates'中使用绝对路径,如“/ *” – 2010-08-10 17:30:01

+0

@ Alejandro:是样式表中的第一个元素,然后是var all_data。我试过路径“/ *”,但它不影响我的结果。 :( – developer 2010-08-10 18:20:57

+0

好问题(+1)。请参阅我的回答以解释问题并获得简单的解决方案。:) – 2010-08-10 20:42:42

回答

3

只要改变

<xsl:variable name="all_data"> 
    <xsl:apply-templates select="*"> 
     <xsl:sort select="name()" /> 
    </xsl:apply-templates> 
    </xsl:variable> 

<xsl:variable name="all_data"> 
    <xsl:apply-templates select="*/*"> 
     <xsl:sort select="name()" /> 
    </xsl:apply-templates> 
    </xsl:variable> 

第一(许多的)问题是

<xsl:apply-templates select="*"> 

选择当前节点的所有子元素。当前节点是/,它有只有一个孩子 - 顶级元素pets

实际上,你要收集的数据为pets所有儿童。

还有其他问题,但我没有空间和时间在这里解决它们。

完整校正代码如下

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:msxsl="urn:schemas-microsoft-com:xslt" 
version="1.0"> 

<xsl:key name="elem_key" match="elem" 
     use="concat(@key, .)" /> 

    <xsl:variable name="all_data"> 
    <xsl:apply-templates select="*//*"> 
     <xsl:sort select="name()" /> 
    </xsl:apply-templates> 
    </xsl:variable> 

    <xsl:template match="*[@NUM&lt;=4]"> 
    <elem key="{name()}"> 
     <xsl:copy-of select="@*" /> 
     <xsl:for-each select="@*"> 
     <xsl:sort select="name()" /> 
     <attribute>|<xsl:value-of 
      select="concat(name(),'=',.)" />|</attribute> 
     </xsl:for-each> 
    </elem> 
    </xsl:template> 

    <xsl:template match="/"> 
    <html> 
     <body> 
     <xsl:for-each select="msxsl:node-set($all_data)"> 
       <xsl:for-each select= 
       "*[generate-id() 
       = 
        generate-id(key('elem_key',concat(@key, .))[1]) 
       ]"> 
       <table > 
        <tr> 
        <td>Element Name</td> 
        <xsl:for-each select="*"> 
         <td> 
         <xsl:value-of select= 
          "substring-before(translate(.,'|',''),'=')" /> 
         </td> 
        </xsl:for-each> 
        </tr> 
        <tr> 
         <td> 
         <xsl:value-of select="@key" /> 
         </td> 
         <xsl:for-each select="*"> 
         <td> 
          <xsl:value-of select= 
          "substring-after 
           (translate(current(),'|',''), 
           '=' 
           )"/> 
         </td> 
         </xsl:for-each> 
        </tr> 
       </table> 
       <p /> 
       </xsl:for-each> 
     </xsl:for-each> 
     </body> 
    </html> 
    </xsl:template> 
</xsl:stylesheet> 

当这个变换所提供的XML文档施加:

<pets name="myPets" NUM="2"> 
    <dog name="allMyDogs" NUM="5"> 
     <dog name="Frank" NUM="3"/> 
     <dog name="Spot" NUM="4"/> 
     <dog name="Rover" NUM="1"/> 
     <dog name="Rupert" NUM="6"/> 
     <cat name="Lucy" NUM="4"/> 
    </dog> 
    <cat name="allMyCats" NUM="4"> 
     <cat name="Simba" NUM="4"/> 
     <cat name="Princess" NUM="5"/> 
     <cat name="Fluffy" NUM="1"/> 
     <cat name="Lucy" NUM="3"/> 
     <cat name="Lucy" NUM="35"/> 
     <cat name="Lucy" NUM="6"/> 
     <cat name="Lucy" NUM="1"/> 
    </cat> 
    <cat name="Lucy" NUM="9"/> 
</pets> 

有用结果(多只动物)产生

<html xmlns:msxsl="urn:schemas-microsoft-com:xslt"> 
    <body> 
     <table> 
      <tr> 
       <td>Element Name</td> 
       <td>name</td> 
       <td>NUM</td> 
      </tr> 
      <tr> 
       <td>cat</td> 
       <td>Lucy</td> 
       <td>4</td> 
      </tr> 
     </table> 
     <p></p> 
     <table> 
      <tr> 
       <td>Element Name</td> 
       <td>name</td> 
       <td>NUM</td> 
      </tr> 
      <tr> 
       <td>cat</td> 
       <td>allMyCats</td> 
       <td>4</td> 
      </tr> 
     </table> 
     <p></p> 
     <table> 
      <tr> 
       <td>Element Name</td> 
       <td>name</td> 
       <td>NUM</td> 
      </tr> 
      <tr> 
       <td>cat</td> 
       <td>Simba</td> 
       <td>4</td> 
      </tr> 
     </table> 
     <p></p> 
     <table> 
      <tr> 
       <td>Element Name</td> 
       <td>name</td> 
       <td>NUM</td> 
      </tr> 
      <tr> 
       <td>cat</td> 
       <td>Fluffy</td> 
       <td>1</td> 
      </tr> 
     </table> 
     <p></p> 
     <table> 
      <tr> 
       <td>Element Name</td> 
       <td>name</td> 
       <td>NUM</td> 
      </tr> 
      <tr> 
       <td>cat</td> 
       <td>Lucy</td> 
       <td>3</td> 
      </tr> 
     </table> 
     <p></p> 
     <table> 
      <tr> 
       <td>Element Name</td> 
       <td>name</td> 
       <td>NUM</td> 
      </tr> 
      <tr> 
       <td>cat</td> 
       <td>Lucy</td> 
       <td>1</td> 
      </tr> 
     </table> 
     <p></p> 
     <table> 
      <tr> 
       <td>Element Name</td> 
       <td>name</td> 
       <td>NUM</td> 
      </tr> 
      <tr> 
       <td>dog</td> 
       <td>Frank</td> 
       <td>3</td> 
      </tr> 
     </table> 
     <p></p> 
     <table> 
      <tr> 
       <td>Element Name</td> 
       <td>name</td> 
       <td>NUM</td> 
      </tr> 
      <tr> 
       <td>dog</td> 
       <td>Spot</td> 
       <td>4</td> 
      </tr> 
     </table> 
     <p></p> 
     <table> 
      <tr> 
       <td>Element Name</td> 
       <td>name</td> 
       <td>NUM</td> 
      </tr> 
      <tr> 
       <td>dog</td> 
       <td>Rover</td> 
       <td>1</td> 
      </tr> 
     </table> 
     <p></p> 
    </body> 
</html> 
+0

@Dimitre:我用// * [@NUM = 4]和// * [@ NUM < = 4]但我仍然没有得到“allMyCats”下的任何孩子 – developer 2010-08-10 21:02:57

+0

@iHeartGreek:然后您使用不同的代码或XML文件。我编辑了我的回复,并将完整的转换,XML文件和结果放在那里。您应该能够复制它们并从转换中获得相同的结果。 – 2010-08-10 21:46:04

+0

@Dimitre:对于代码中显示的// * [@ NUM < = 4] ..我不希望让名为Fluffy和Simba的猫回来吗?哦,露西NUM = 3和露西NUM = 1也从你的结果中缺失。我很抱歉,但我没有收到与此代码(确切的复制粘贴)正确的结果:(我在泡菜 – developer 2010-08-10 22:00:41

0

*[generate-id()=generate-id(key('elem_key',concat(@key, .))[1])]您已经钥匙做一个匹配少数情况下选择,然后你问的只是先用[1]

我什么不清楚你是想为正确的结果布局进一步建议