Python 在具有相同标记的不同位置更改xml值
我有一个python脚本,它使用lxml来更改特定标记的值。我有以下xmlPython 在具有相同标记的不同位置更改xml值,python,xml,xpath,lxml,Python,Xml,Xpath,Lxml,我有一个python脚本,它使用lxml来更改特定标记的值。我有以下xml <gmd:CI_Citation> <gmd:date> <gmd:CI_Date> <gmd:date> <gco:Da
<gmd:CI_Citation>
<gmd:date>
<gmd:CI_Date>
<gmd:date>
<gco:Date>**1900-01-01**</gco:Date>
</gmd:date>
<gmd:dateType>
<gmd:CI_DateTypeCode codeList="http://standards.iso.org/ittf/PubliclyAvailableStandards/ISO_19139_Schemas/resources/Codelist/gmxCodelists.xml#CI_DateTypeCode" codeListValue="publication">Publication</gmd:CI_DateTypeCode>
</gmd:dateType>
</gmd:CI_Date>
</gmd:date>
<gmd:date>
<gmd:CI_Date>
<gmd:date>
<gco:Date>**1900-01-01**</gco:Date>
</gmd:date>
<gmd:dateType>
<gmd:CI_DateTypeCode codeList="http://standards.iso.org/ittf/PubliclyAvailableStandards/ISO_19139_Schemas/resources/Codelist/gmxCodelists.xml#CI_DateTypeCode" codeListValue="creation">Creation</gmd:CI_DateTypeCode>
</gmd:dateType>
</gmd:CI_Date>
</gmd:date>
<gmd:date>
<gmd:CI_Date>
<gmd:date>
<gco:Date>**1900-01-01**</gco:Date>
</gmd:date>
<gmd:dateType>
<gmd:CI_DateTypeCode codeList="http://standards.iso.org/ittf/PubliclyAvailableStandards/ISO_19139_Schemas/resources/Codelist/gmxCodelists.xml#CI_DateTypeCode" codeListValue="revision">Revision</gmd:CI_DateTypeCode>
</gmd:dateType>
</gmd:CI_Date>
</gmd:date>
</gmd:CI_Citation>
我正在使用以下函数更改值
def updateXMLTag (tag, value):
xmlValue = root.xpath(tag)
xmlValue[0].text = str(value)
使用xpath访问特定标记以便更改值的最佳方法是什么?这是我使用xpath访问特定元素并编辑它们的方法:
# Find the best implementation available on the platform
try:
from cStringIO import StringIO
except:
from StringIO import StringIO
from lxml import etree
# proper namespaces added to get valid xml
xmlstr = StringIO("""<gmd:CI_Citation xmlns:gmd="http://gmd.example.com" xmlns:gco="http://gco.example.com">
<gmd:date>
<gmd:CI_Date>
<gmd:date>
<gco:Date>1900-01-01</gco:Date>
</gmd:date>
<gmd:dateType>
<gmd:CI_DateTypeCode codeList="http://standards.iso.org/ittf/PubliclyAvailableStandards/ISO_19139_Schemas/resources/Codelist/gmxCodelists.xml#CI_DateTypeCode" codeListValue="publication">Publication</gmd:CI_DateTypeCode>
</gmd:dateType>
</gmd:CI_Date>
</gmd:date>
<gmd:date>
<gmd:CI_Date>
<gmd:date>
<gco:Date>1900-01-01</gco:Date>
</gmd:date>
<gmd:dateType>
<gmd:CI_DateTypeCode codeList="http://standards.iso.org/ittf/PubliclyAvailableStandards/ISO_19139_Schemas/resources/Codelist/gmxCodelists.xml#CI_DateTypeCode" codeListValue="creation">Creation</gmd:CI_DateTypeCode>
</gmd:dateType>
</gmd:CI_Date>
</gmd:date>
<gmd:date>
<gmd:CI_Date>
<gmd:date>
<gco:Date>1900-01-01</gco:Date>
</gmd:date>
<gmd:dateType>
<gmd:CI_DateTypeCode codeList="http://standards.iso.org/ittf/PubliclyAvailableStandards/ISO_19139_Schemas/resources/Codelist/gmxCodelists.xml#CI_DateTypeCode" codeListValue="revision">Revision</gmd:CI_DateTypeCode>
</gmd:dateType>
</gmd:CI_Date>
</gmd:date>
</gmd:CI_Citation>""")
tree = etree.parse(xmlstr)
这三个元素由唯一的属性值区分,
可通过一个简单的函数hasattr
def hasattr(elem, att, val):
try:
return elem.attrib[att] == val
except:
return False
目标[0]codeListValue/text节点:“发布”/“发布”
目标[1]codeListValue/text节点:“创建”/“创建”
目标[2]代码列表值/文本节点:“修订”/“修订”
哪一个需要改变
hasattr(targets[0], 'codeListValue', 'publication') # True
hasattr(targets[1], 'codeListValue', 'creation') # True
hasattr(targets[2], 'codeListValue', 'publication') # False
# Let's change one of them
t1 = targets[1]
t1.text = 'New Creation' # change text node
# and/or change attribute
t1.attrib['codeListValue'] = 'Latest Creation'
最后,我们将结果保存到一个文件中
tree.write("output1.xml")
编辑1
在这里,我们导航到已经找到的需要更改的目标[1]的cousin1(gco:Date):
t1 = targets[1]
parent1 = t1.getparent()
date1 = parent1.getprevious()
cousin1 = date1.getchildren()
len(cousin1) #1
cousin1[0].text #'1900-01-01'
# change the date
cousin1[0].text = '2017-5-3'
# again, write the result
tree.write("out456.xml")
XML输入格式不正确,因为没有声明
gmd
和gco
前缀。这就是XML的格式。(虽然我只发布了xml文档的一部分)。我对xml问题发表了多次评论,任何带有名称空间(以冒号分隔的前缀)的xml都始终包含根标记或定义名称空间URI的任何位置(搜索xmlns=
)。请更新示例帖子。@MapMan:您不能仅凭声明“XML就是这样”就获取XML文档的一部分。您发布的不是XML。lxml会被它噎住的。名称空间及其前缀看起来可能只是一个小细节,但它们的存在是有原因的,不管你喜不喜欢。我接受你的观点,但不确定发布一个400行xml文档是否是一个好主意,因此我只发布了相关的位。感谢这个示例,但它不会更改gco:Date,这是需要更改的内容,而不是codeListvalue的文本。@MapMan,我已经编辑了我的答案,以显示如何更改日期。
tree.write("output1.xml")
t1 = targets[1]
parent1 = t1.getparent()
date1 = parent1.getprevious()
cousin1 = date1.getchildren()
len(cousin1) #1
cousin1[0].text #'1900-01-01'
# change the date
cousin1[0].text = '2017-5-3'
# again, write the result
tree.write("out456.xml")