这是jenkins xml文件的一部分。
我想用xpath提取project_name
的defaultValue。
我在这种情况下的值为*****
。
<?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选择。
答案 0 :(得分:2)
XPath对您问题的回答是
/project/properties/hudson.model.ParametersDefinitionProperty/parameterDefinitions/hudson.model.StringParameterDefinition[name = 'project_name']/defaultValue/text()
将选择唯一的结果
*****
鉴于您的实际文档没有命名空间。您不需要访问父元素也不需要访问兄弟轴。
甚至etree应该支持这种XPath表达式,但它可能不支持 - 请参阅comment by har07。
我再次想到这一点,我认为在python中循环是错误的方法。这应该可以通过xpath选择。
是的,我同意。如果要从文档中选择单个值,请使用XPath表达式选择它并将其直接存储为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]
输出:
*****
答案 1 :(得分:1)
您可以尝试lxml.etree,如下所示 - 我使用循环来选择具有相同位置的所有节点。
所需的xpath的示例是 - 我使用了relative xpath,因为它非常有用,包含长节点路径。
.//hudson.model.StringParameterDefinition/name[contains(text(),'project_name')]/following-sibling::defaultValue
OR
.//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', '*****']
['*****']
['*****']