XPath的结果是不正确的 - 通过整个XML不会
所以,我有我的手一个非常混乱的问题..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<=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<=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上。
任何人都可以帮助我修复此代码,以便它返回正确的结果?我很沮丧! :(
谢谢!
只要改变:
<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<=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>
@Dimitre:我用// * [@NUM = 4]和// * [@ NUM < = 4]但我仍然没有得到“allMyCats”下的任何孩子 – developer 2010-08-10 21:02:57
@iHeartGreek:然后您使用不同的代码或XML文件。我编辑了我的回复,并将完整的转换,XML文件和结果放在那里。您应该能够复制它们并从转换中获得相同的结果。 – 2010-08-10 21:46:04
@Dimitre:对于代码中显示的// * [@ NUM < = 4] ..我不希望让名为Fluffy和Simba的猫回来吗?哦,露西NUM = 3和露西NUM = 1也从你的结果中缺失。我很抱歉,但我没有收到与此代码(确切的复制粘贴)正确的结果:(我在泡菜 – developer 2010-08-10 22:00:41
*[generate-id()=generate-id(key('elem_key',concat(@key, .))[1])]
您已经钥匙做一个匹配少数情况下选择,然后你问的只是先用[1]
我什么不清楚你是想为正确的结果布局进一步建议
没有完整的样式表,我只能猜测...如果var'all_data'被声明为样式表的顶层元素,那么我建议在'xsl:apply-templates'中使用绝对路径,如“/ *” – 2010-08-10 17:30:01
@ Alejandro:是样式表中的第一个元素,然后是var all_data。我试过路径“/ *”,但它不影响我的结果。 :( –
developer
2010-08-10 18:20:57
好问题(+1)。请参阅我的回答以解释问题并获得简单的解决方案。:) – 2010-08-10 20:42:42