我正在编写一个xslt样式表来将xml转换为另一个xml。
以下是原始xml的简化版本:
<eml>
<datatable>
<physical>
<distribution id="100"/>
</physical>
</datatable>
<software>
<implementation>
<distribution id="200"/>
</implementation>
</software>
<additionalMetadata>
<describes>100</describes>
<describes>200</describes>
<describes>300</describes>
<describes>400</describes>
</additionalMetadata>
</eml>
我尝试使用Xpath来选择“describe”的节点集,该节点集的值不等于//physical/distribution
或software/implementation/distribution
的id值。在上面的例子中,我想得到节点集:
<deseribes>300</describes>
<deseribes>400</describes>
(100和200是//physical/distribution
或software/implementation/distribution
的属性ID值。
<xsl:with-param name="describes-list"
select="./describes[//physical/distribution/@id !=. and
//software/implementation/distribution/@id != .] "/>
它适用于上面的例子。但是,数据表和软件的元素是可重复的。所以这个xml是有效的:
<eml>
<datatable>
<physical>
<distribution id="100"/>
</physical>
</datatable>
<datatable>
<physical>
<distribution id="300"/>
</physical>
</datatable>
<software>
<implementation>
<distribution id="200"/>
</implementation>
</software>
<additionalMetadata>
<describes>100</describes>
<describes>200</describes>
<describes>300</describes>
<describes>400</describes>
</additionalMetadata>
</eml>
但是我的xslt在上面的例子中不起作用:(
你介意对此有所了解吗?提前谢谢!
荆
答案 0 :(得分:19)
这是一个经常犯的错误。当一个或两个操作数是节点集时,切勿使用XPath's "!=" operator。
value != node-set
定义为
value
不等于string(n)
你想要的是
value
不等于节点集中的任何节点。
这可以用以下方式表达:
value = node-set
为真,例如:
value = string(n)
然后
not(value = node-set)
为真,例如
value = string(n)
因此,以下XPath表达式将选择所需的节点:
/*/*/describes[not(. = ../../*/physical/distribution/@id) and not(. = ../../*/implementation/distribution/@id)]
我个人更愿意将上下文节点与两个节点集的并集进行一次比较:
/*/*/describes [not(. = (../../*/physical/distribution/@id | ../../*/implementation/distribution/@id ) ) ]
请注意我避免使用“//”缩写。它通常非常昂贵(效率低下),只有在我们不知道XML文档的结构时才应该使用它。
当然,上述XPath表达式必须针对以下XML文档(问题中提供的第二个)进行评估:
<eml> <datatable> <physical> <distribution id="100"/> </physical> </datatable> <datatable> <physical> <distribution id="300"/> </physical> </datatable> <software> <implementation> <distribution id="200"/> </implementation> </software> <additionalMetadata> <describes>100</describes> <describes>200</describes> <describes>300</describes> <describes>400</describes> </additionalMetadata> </eml>