XPath通过子节点的完全匹配来选择

时间:2016-06-23 16:29:18

标签: xml xpath

示例XML:

<cacheFile>
    <workflows>
        <workflow wfid="999" name="John" >
            <attached docid="001" />
            <attached docid="002" />
        </workflow>
        <workflow wfid="888" name="John" >
            <attached docid="001" />
            <attached docid="002" />
            <attached docid="003" />
        </workflow>
    </workflows>
    <otherData/>
</cacheFile>

如上面的代码段所示,我有一个XML文件,其中包含有关各种工作流程项的数据;每个工作流元素都包含自己的id,已分配的工作者的名称以及附加的文档ID列表。仅使用name属性和文档ID列表,我需要选择正确的工作流ID。

我想出了以下几乎按预期工作的XPath查询:

//cache/workflows/workflow[@name='John' and ./document[@id='001'] and ./document[@id='002']]"

问题是,此查询返回两个工作流程项;我需要它只返回完全匹配(wfid = 999)。有许多方法可以手动对结果进行排序,但我认为必须有一些我无法找到的XPath函数可能会限制查询执行期间的结果。也许是限制子元素数量的约束?

1 个答案:

答案 0 :(得分:0)

您可以计算attached docid属性:

x = """<cacheFile>
    <workflows>
        <workflow wfid="999" name="John" >
            <attached docid="001" />
            <attached docid="002" />
        </workflow>
        <workflow wfid="888" name="John" >
            <attached docid="001" />
            <attached docid="002" />
            <attached docid="003" />
        </workflow>
    </workflows>
    <otherData/>
</cacheFile>"""

import lxml.etree as et

xml = et.fromstring(x)


print(xml.xpath("//workflows/workflow[count(./attached/@docid) < 3]"))

或者只是计算附件就足够了:

"//workflows/workflow[count(./attached) < 3]"

您可以使用doc值并确保只有2:

xpath("//workflows/workflow[./attached[3]='' and ./attached[1]/@docid=001 and ./attached[2]/@docid=002]")

当然,如果你可以使用wifid,那会更简单:

print(xml.xpath('//workflows/workflow[@wfid="999"]'))