美好的一天!假设以下XML:
<store>
<book id="b1"></book>
<book id="b2"></book>
</store>
<store>
<book id="b2"></book>
<book id="b4"></book>
</store>
<booklist>
<book id="b1"></book>
<book id="b2"></book>
<book id="b3"></book>
</booklist>
我想写一个Xpath查询,它将选择商店
把他们所有的书放在书单中。在我的例子中,它是第一个商店,但不是第二个商店
我试过了
//store[./book/@id = /booklist/book/@id]
但它选择的商店至少包含一本普通书籍,而不是所有书籍
另外,没有为两个节点列表找到任何类似“包含”的谓词,所以我缺乏想法。
编辑:我非常感谢任何帮助,但我更喜欢使用“基本”Xpath功能(如果存在)的解决方案。这对我来说是一种新语言。但是,感谢所有回复的人。
答案 0 :(得分:4)
使用强>:
/*/store[not(book[not(@id = /*/booklist/*/@id)])]
应用于此XML文档(提供的文档,通过使用单个顶部元素包装而构建良好):
<t>
<store>
<book id="b1"></book>
<book id="b2"></book>
</store>
<store>
<book id="b2"></book>
<book id="b4"></book>
</store>
<booklist>
<book id="b1"></book>
<book id="b2"></book>
<book id="b3"></book>
</booklist>
</t>
选择了需要的stor
元素:
<store>
<book id="b1"/>
<book id="b2"/>
</store>
使用XSLT作为XPath主机的验证:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<xsl:copy-of select=
"/*/store[not(book[not(@id = /*/booklist/*/@id)])]"/>
</xsl:template>
</xsl:stylesheet>
当对上述XML文档应用此XSLT转换时,会生成所需的正确结果:
<store>
<book id="b1"/>
<book id="b2"/>
</store>
<强>解释强>:
表达式:
/*/store[not(book[not(@id = /*/booklist/*/@id)])]
表示:
选择所有store
元素(top元素的子元素),使得book
属性的值为id
之一的id
(子)中只有一个book
1}}属性booklist
的{{1}} s(子)的属性值。
答案 1 :(得分:1)
这是一个可行的解决方案
//store[not(book/@id = //store/book[not(@id = //booklist/book/@id)]/@id)]
应用于此xml(为了清晰测试而添加商店name
),它选择商店1
&amp; 3
<xml>
<store name="1">
<book id="b1"/>
<book id="b2"/>
</store>
<store name="2">
<book id="b2"/>
<book id="b4"/>
</store>
<store name="3">
<book id="b1"/>
<book id="b3"/>
</store>
<store name="4">
<book id="b3"/>
<book id="b4"/>
</store>
<booklist>
<book id="b1"/>
<book id="b2"/>
<book id="b3"/>
</booklist>
</xml>
解释(两个否定结果为正)
//store[not(book/@id = # get me all stores that don't have a book/@id that is in the list below
//store/book[not(@id = //booklist/book/@id)]/@id) # get me a list of store/book/@id where @id is not in the book list
]
答案 2 :(得分:0)
你可能需要使用函数,试试这个:
for $bid in //booklist/book/@id
if(every $id in //store/book/@id satisfies $id=$bid ) then fn:true()
else fn:false()
不确定它是否有效,但只是给你一个想法。
答案 3 :(得分:0)
我想认为可以使用exslt set extensions
E.g:
//store[count(./book/@id) = count(set:intersection(./book/@id,//booklist/book/@id))]
但是intersection
似乎没有按照我期望的那样在python的lxml.etree