访问下一个兄弟的文本
Access text of next sibling
这是 jenkins xml 文件的一部分。
我想用 xpath 提取 project_name
的默认值。
在这种情况下,值为 *****
。
<?xml version='1.0' encoding='UTF-8'?>
<project>
<properties>
<hudson.model.ParametersDefinitionProperty>
<parameterDefinitions>
<hudson.model.StringParameterDefinition>
<name>customer_name</name>
<description></description>
<defaultValue>my_customer</defaultValue>
</hudson.model.StringParameterDefinition>
<hudson.model.StringParameterDefinition>
<name>project_name</name>
<description></description>
<defaultValue>*****</defaultValue>
</hudson.model.StringParameterDefinition>
</parameterDefinitions>
</hudson.model.ParametersDefinitionProperty>
</properties>
</project>
我使用 python 的 etree,但是 AFAIK 这并不重要,因为这是一个 xpath 问题。
我目前的 xpath 知识有限。我目前的做法:
for name_tag in config.findall('.//name'):
if name_tag.text=='project_host':
default=name_tag.getparent().findall('defaultValue')[0].text
这里我得到AttributeError: 'Element' object has no attribute 'getparent'
我又想了想,我认为在python中循环是错误的做法。这应该可以通过 xpath 选择。
您可以尝试 lxml.etree 如下 - 我使用循环 select 所有具有相同位置的节点。
所需 xpath 的示例是 - 我使用了 relative xpath 因为它在长节点路径的情况下非常有用。
.//hudson.model.StringParameterDefinition/name[contains(text(),'project_name')]/following-sibling::defaultValue
或
.//hudson.model.StringParameterDefinition/name[contains(text(),'project_name')]/following::defaultValue[1]
from lxml import etree as et
data = """<?xml version='1.0' encoding='UTF-8'?>
<project>
<properties>
<hudson.model.ParametersDefinitionProperty>
<parameterDefinitions>
<hudson.model.StringParameterDefinition>
<name>customer_name</name>
<description></description>
<defaultValue>my_customer</defaultValue>
</hudson.model.StringParameterDefinition>
<hudson.model.StringParameterDefinition>
<name>project_name</name>
<description></description>
<defaultValue>*****</defaultValue>
</hudson.model.StringParameterDefinition>
</parameterDefinitions>
</hudson.model.ParametersDefinitionProperty>
</properties>
</project>"""
tree = et.fromstring(data)
print [i.text for i in tree.xpath(".//hudson.model.StringParameterDefinition/defaultValue")]
print [i.text for i in tree.xpath(".//hudson.model.StringParameterDefinition/name[contains(text(),'project_name')]/following-sibling::defaultValue")]
print [i.text for i in tree.xpath(".//hudson.model.StringParameterDefinition/name[contains(text(),'project_name')]/following::defaultValue[1]")]
输出-
['my_customer', '*****']
['*****']
['*****']
您问题的 XPath 答案是
/project/properties/hudson.model.ParametersDefinitionProperty/parameterDefinitions/hudson.model.StringParameterDefinition[name = 'project_name']/defaultValue/text()
这将 select 作为唯一的结果
*****
鉴于您的实际文档没有命名空间。您不需要访问父元素或兄弟轴。
即使 etree 也应该支持这种 XPath 表达式,但它可能不支持 - 请参阅 。
I thought about this again, and I think that looping in python is the wrong approach. This should be selectable via xpath.
是的,我同意。如果您想 select 文档中的单个值,请使用 XPath 表达式 select 并将其直接存储为 Python 字符串,而无需遍历元素。
lxml 的完整示例
from lxml import etree
from StringIO import StringIO
document_string = """<project>
<properties>
<hudson.model.ParametersDefinitionProperty>
<parameterDefinitions>
<hudson.model.StringParameterDefinition>
<name>customer_name</name>
<description></description>
<defaultValue>my_customer</defaultValue>
</hudson.model.StringParameterDefinition>
<hudson.model.StringParameterDefinition>
<name>project_name</name>
<description></description>
<defaultValue>*****</defaultValue>
</hudson.model.StringParameterDefinition>
</parameterDefinitions>
</hudson.model.ParametersDefinitionProperty>
</properties>
</project>"""
tree = etree.parse(StringIO(document_string))
result_list = tree.xpath("/project/properties/hudson.model.ParametersDefinitionProperty/parameterDefinitions/hudson.model.StringParameterDefinition[name = 'project_name']/defaultValue/text()")
print result_list[0]
输出:
*****
这是 jenkins xml 文件的一部分。
我想用 xpath 提取 project_name
的默认值。
在这种情况下,值为 *****
。
<?xml version='1.0' encoding='UTF-8'?>
<project>
<properties>
<hudson.model.ParametersDefinitionProperty>
<parameterDefinitions>
<hudson.model.StringParameterDefinition>
<name>customer_name</name>
<description></description>
<defaultValue>my_customer</defaultValue>
</hudson.model.StringParameterDefinition>
<hudson.model.StringParameterDefinition>
<name>project_name</name>
<description></description>
<defaultValue>*****</defaultValue>
</hudson.model.StringParameterDefinition>
</parameterDefinitions>
</hudson.model.ParametersDefinitionProperty>
</properties>
</project>
我使用 python 的 etree,但是 AFAIK 这并不重要,因为这是一个 xpath 问题。
我目前的 xpath 知识有限。我目前的做法:
for name_tag in config.findall('.//name'):
if name_tag.text=='project_host':
default=name_tag.getparent().findall('defaultValue')[0].text
这里我得到AttributeError: 'Element' object has no attribute 'getparent'
我又想了想,我认为在python中循环是错误的做法。这应该可以通过 xpath 选择。
您可以尝试 lxml.etree 如下 - 我使用循环 select 所有具有相同位置的节点。
所需 xpath 的示例是 - 我使用了 relative xpath 因为它在长节点路径的情况下非常有用。
.//hudson.model.StringParameterDefinition/name[contains(text(),'project_name')]/following-sibling::defaultValue
或
.//hudson.model.StringParameterDefinition/name[contains(text(),'project_name')]/following::defaultValue[1]
from lxml import etree as et
data = """<?xml version='1.0' encoding='UTF-8'?>
<project>
<properties>
<hudson.model.ParametersDefinitionProperty>
<parameterDefinitions>
<hudson.model.StringParameterDefinition>
<name>customer_name</name>
<description></description>
<defaultValue>my_customer</defaultValue>
</hudson.model.StringParameterDefinition>
<hudson.model.StringParameterDefinition>
<name>project_name</name>
<description></description>
<defaultValue>*****</defaultValue>
</hudson.model.StringParameterDefinition>
</parameterDefinitions>
</hudson.model.ParametersDefinitionProperty>
</properties>
</project>"""
tree = et.fromstring(data)
print [i.text for i in tree.xpath(".//hudson.model.StringParameterDefinition/defaultValue")]
print [i.text for i in tree.xpath(".//hudson.model.StringParameterDefinition/name[contains(text(),'project_name')]/following-sibling::defaultValue")]
print [i.text for i in tree.xpath(".//hudson.model.StringParameterDefinition/name[contains(text(),'project_name')]/following::defaultValue[1]")]
输出-
['my_customer', '*****']
['*****']
['*****']
您问题的 XPath 答案是
/project/properties/hudson.model.ParametersDefinitionProperty/parameterDefinitions/hudson.model.StringParameterDefinition[name = 'project_name']/defaultValue/text()
这将 select 作为唯一的结果
*****
鉴于您的实际文档没有命名空间。您不需要访问父元素或兄弟轴。
即使 etree 也应该支持这种 XPath 表达式,但它可能不支持 - 请参阅
I thought about this again, and I think that looping in python is the wrong approach. This should be selectable via xpath.
是的,我同意。如果您想 select 文档中的单个值,请使用 XPath 表达式 select 并将其直接存储为 Python 字符串,而无需遍历元素。
lxml 的完整示例
from lxml import etree
from StringIO import StringIO
document_string = """<project>
<properties>
<hudson.model.ParametersDefinitionProperty>
<parameterDefinitions>
<hudson.model.StringParameterDefinition>
<name>customer_name</name>
<description></description>
<defaultValue>my_customer</defaultValue>
</hudson.model.StringParameterDefinition>
<hudson.model.StringParameterDefinition>
<name>project_name</name>
<description></description>
<defaultValue>*****</defaultValue>
</hudson.model.StringParameterDefinition>
</parameterDefinitions>
</hudson.model.ParametersDefinitionProperty>
</properties>
</project>"""
tree = etree.parse(StringIO(document_string))
result_list = tree.xpath("/project/properties/hudson.model.ParametersDefinitionProperty/parameterDefinitions/hudson.model.StringParameterDefinition[name = 'project_name']/defaultValue/text()")
print result_list[0]
输出:
*****