Python lxml xpath find node with text()=concat('x', 'y')

问题描述 投票:0回答:1

我想用python lxml xpath解析一个xml文件,结构是这样的。

<body>
  <tu changedate="20190822T080742Z" creationdate="20190822T085527Z" creationid="blank" changeid="blank">
    <prop type="client"> </prop>
    <prop type="project"> </prop>
    <prop type="domain"> </prop>
    <prop type="subject"> </prop>
    <prop type="corrected">no</prop>
    <prop type="aligned">no</prop>
    <prop type="x-document">Test_EN.docx</prop>
    <prop type="x-Project Id">0001</prop>
    <prop type="x-Product group">A</prop>
    <prop type="x-Product">A</prop>
    <prop type="x-Product">B</prop>
    <prop type="x-TestList">TestValue1</prop>
    <prop type="x-TestList">TestValue2</prop>
    <prop type="x-Sample">SampleText</prop>
    <prop type="x-Test">TestText</prop>
    <prop type="x-Name">TestName</prop>

为了用函数动态地找到节点,我把要找的节点的名字和值保存到变量名中。

node_name = x-Sample
node_value = SampleText
xpath_expression = f'//body/tu/prop[@type="{node_name}"][text()="{node_value}"]'
elements = tree.xpath(xpath_expression)

问题是node_value可以包含双引号,因此产生一个无效的xpath表达式。由于我被lxml卡住了,而且它使用的是xpath 1.0,我无法在字符串中转义。

通过stackoverflow查找,我发现显然只有在xpath 1.0中使用concat才能做到这一点。我还找到了下面发布的函数。

def xpath_string_escape(input_str):
    """ creates a concatenation of alternately-quoted strings that is always a valid XPath expression """
    parts = input_str.split('"')
    return "concat('" + "', \"'\" , '".join(parts) + "', '')"

然后就得到了这个

xpath_expression = '//body/tu/tuv/prop[@type="x-Sample"][text()="concat('SampleText', '')"]'

然而这并没有返回我想要的节点。

python xml xpath lxml
1个回答
0
投票

另一种方法 你可以用.NET去掉节点值中的双引号。

node_value = translate(//prop[@type="x-Sample"]/text(),'"',"")

然后用contains()代替text()来构建你的XPath表达式。

xpath_expression = f'//body/tu/prop[@type="{node_name}"][contains(.,"{node_value}")]'
© www.soinside.com 2019 - 2024. All rights reserved.