【发布时间】:2015-09-25 06:51:59
【问题描述】:
我正在使用lxml 库来读取 xml 模板、插入/更改一些元素并保存生成的 xml。我使用etree.Element 和etree.SubElement 方法即时创建的元素之一:
tree = etree.parse(r'xml_archive\templates\metadata_template_pts.xml')
root = tree.getroot()
stream = []
for element in root.iter():
if isinstance(element.tag, basestring):
stream.append(element.tag)
# Find "keywords" element and insert a new "theme" element
if element.tag == 'keywords' and 'theme' not in stream:
theme = etree.Element('theme')
themekt = etree.SubElement(theme, 'themekt').text = 'None'
for tk in themekeys:
themekey = etree.SubElement(theme, 'themekey').text = tk
element.insert(0, theme)
很好地打印到屏幕上print etree.tostring(theme, pretty_print=True):
<theme>
<themekt>None</themekt>
<themekey>Hydrogeology</themekey>
<themekey>Stratigraphy</themekey>
<themekey>Floridan aquifer system</themekey>
<themekey>Geology</themekey>
<themekey>Regional Groundwater Availability Study</themekey>
<themekey>USGS</themekey>
<themekey>United States Geological Survey</themekey>
<themekey>thickness</themekey>
<themekey>altitude</themekey>
<themekey>extent</themekey>
<themekey>regions</themekey>
<themekey>upper confining unit</themekey>
<themekey>FAS</themekey>
<themekey>base</themekey>
<themekey>geologic units</themekey>
<themekey>geology</themekey>
<themekey>extent</themekey>
<themekey>inlandWaters</themekey>
</theme>
但是,当使用etree.ElementTree(root).write(out_xml_file, method='xml', pretty_print=True) 写出 xml 时,此元素在输出文件中被展平:
<theme><themekt>None</themekt><themekey>Hydrogeology</themekey><themekey>Stratigraphy</themekey><themekey>Floridan aquifer system</themekey><themekey>Geology</themekey><themekey>Regional Groundwater Availability Study</themekey><themekey>USGS</themekey><themekey>United States Geological Survey</themekey><themekey>thickness</themekey><themekey>altitude</themekey><themekey>extent</themekey><themekey>regions</themekey><themekey>upper confining unit</themekey><themekey>FAS</themekey><themekey>base</themekey><themekey>geologic units</themekey><themekey>geology</themekey><themekey>extent</themekey><themekey>inlandWaters</themekey></theme>
文件的其余部分写得很好,但是这个特殊的元素正在引起(纯粹是审美的)麻烦。关于我做错了什么的任何想法?
下面是来自模板 xml 文件的标记的 sn-p(将其保存为“template.xml”以在底部使用代码 sn-p 运行)。标签的扁平化仅在我解析现有文件并插入新元素时发生,而不是在使用 lxml 从头开始创建 xml 时发生。
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="fgdc_classic.xsl"?>
<metadata xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://water.usgs.gov/GIS/metadata/usgswrd/fgdc-std-001-1998.xsd">
<keywords>
<theme>
<themekt>ISO 19115 Topic Categories</themekt>
<themekey>environment</themekey>
<themekey>geoscientificInformation</themekey>
<themekey>inlandWaters</themekey>
</theme>
<place>
<placekt>None</placekt>
<placekey>Florida</placekey>
<placekey>Georgia</placekey>
<placekey>Alabama</placekey>
<placekey>South Carolina</placekey>
</place>
</keywords>
</metadata>
下面是与标记的sn-p一起使用的sn-p代码(上):
# Create new theme element to insert into root
themekeys = ['Hydrogeology', 'Stratigraphy', 'inlandWaters']
tree = etree.parse(r'template.xml')
root = tree.getroot()
stream = []
for element in root.iter():
if isinstance(element.tag, basestring):
stream.append(element.tag)
# Edit theme keywords
if element.tag == 'keywords':
theme = etree.Element('theme')
themekt = etree.SubElement(theme, 'themekt').text = 'None'
for tk in themekeys:
themekey = etree.SubElement(theme, 'themekey').text = tk
element.insert(0, theme)
# Write XML to new file
out_xml_file = 'test.xml'
etree.ElementTree(root).write(out_xml_file, method='xml', pretty_print=True)
with open(out_xml_file, 'r') as f:
lines = f.readlines()
with open(out_xml_file, 'w') as f:
f.write('<?xml version="1.0" encoding="UTF-8"?>\n')
for line in lines:
f.write(line)
【问题讨论】:
-
我无法重现此内容。您能否提供一个简短的代码 sn-p 来演示我可以剪切和粘贴的问题?我无法按原样运行问题中的代码(一方面,我没有您的 XML 模板)。
-
@mzjn 我刚刚从模板文件中添加了标记的 sn-p。标签的扁平化仅在我解析现有文件并插入新元素时发生,而不是在使用
lxml从头开始创建 xml 时发生。它可能与空格有关——我尝试使用忽略空格的解析器,并且许多先前嵌套的元素在写入文件后变得扁平,有时它们中的许多元素在一行中一起运行。 -
“扁平化”是一种结构操作——指的是从子树中取出叶子并将它们向上移动到顶层。我已经调整了标题以专门指代空格。
标签: python xml xml-parsing lxml