使用 ElementTree 保存 XML 文件
Posted
技术标签:
【中文标题】使用 ElementTree 保存 XML 文件【英文标题】:Saving XML files using ElementTree 【发布时间】:2012-02-17 11:25:17 【问题描述】:我正在尝试开发简单的 Python (3.2) 代码来读取 XML 文件,进行一些 更正 并将它们存储回来。但是,在存储步骤中,ElementTree 添加了这个命名空间命名法。例如:
<ns0:trk>
<ns0:name>ACTIVE LOG</ns0:name>
<ns0:trkseg>
<ns0:trkpt lat="38.5" lon="-120.2">
<ns0:ele>6.385864</ns0:ele>
<ns0:time>2011-12-10T17:46:30Z</ns0:time>
</ns0:trkpt>
<ns0:trkpt lat="40.7" lon="-120.95">
<ns0:ele>5.905273</ns0:ele>
<ns0:time>2011-12-10T17:46:51Z</ns0:time>
</ns0:trkpt>
<ns0:trkpt lat="43.252" lon="-126.453">
<ns0:ele>7.347168</ns0:ele>
<ns0:time>2011-12-10T17:52:28Z</ns0:time>
</ns0:trkpt>
</ns0:trkseg>
</ns0:trk>
代码sn-p如下:
def parse_gpx_data(gpxdata, tzname=None, npoints=None, filter_window=None,
output_file_name=None):
ET = load_xml_library();
def find_trksegs_or_route(etree, ns):
trksegs=etree.findall('.//'+ns+'trkseg')
if trksegs:
return trksegs, "trkpt"
else: # try to display route if track is missing
rte=etree.findall('.//'+ns+'rte')
return rte, "rtept"
# try GPX10 namespace first
try:
element = ET.XML(gpxdata)
except ET.ParseError as v:
row, column = v.position
print ("error on row %d, column %d:%d" % row, column, v)
print ("%s" % ET.tostring(element))
trksegs,pttag=find_trksegs_or_route(element, GPX10)
NS=GPX10
if not trksegs: # try GPX11 namespace otherwise
trksegs,pttag=find_trksegs_or_route(element, GPX11)
NS=GPX11
if not trksegs: # try without any namespace
trksegs,pttag=find_trksegs_or_route(element, "")
NS=""
# Store the results if requested
if output_file_name:
ET.register_namespace('', GPX11)
ET.register_namespace('', GPX10)
ET.ElementTree(element).write(output_file_name, xml_declaration=True)
return;
我尝试过使用register_namespace
,但没有得到肯定的结果。
此版本的 ElementTree 1.3 是否有任何特定更改?
【问题讨论】:
如果我理解你的问题,请告诉我,你想要<trk>
而不是<ns0:trk>
等等?
正确。我想要 看来您必须声明您的命名空间,这意味着您需要将 xml 的第一行更改为:
<ns0:trk>
类似于:
<ns0:trk xmlns:ns0="uri:">
一旦这样做,您将不再获得ParseError: for unbound prefix: ...
,并且:
elem.tag = elem.tag[(len('uri:'):]
将删除命名空间。
【讨论】:
嗨瑞克。我展示的示例 XML 是 输出。解析良好的输入 XML 没有“ns0:”前缀。它只是标准的 GPX 代码。 如果element = ET.XML(gpxdata)
行给你一个带有ns0
的元素,那么“问题”在gpxdata 中,在这种情况下你必须选择:“修复”gpxdata 或找出标准的原因parser 会这样做并为ET.XML
构建一个新的。
原始 gpxdata 没有任何 ns0
条目。但是,Rik 的提示让我找到了解决方案。基本上,ET.register_namespace('', GPX11)
ET.register_namespace('', GPX10)
应该在阅读之前完成,即ET.XML
。【参考方案2】:
为了避免ns0
前缀,默认命名空间应该设置在之前读取XML数据。
ET.register_namespace('', "http://www.topografix.com/GPX/1/1")
ET.register_namespace('', "http://www.topografix.com/GPX/1/0")
【讨论】:
看起来不像以前了。我能够读取 XML 文件并获取命名空间,并且只有在设置 register_namespace 之后。 tree = ET.parse(str(udx_path)) root = tree.getroot() ns = # 提取根元素 'udx' 的命名空间:root.tag[1:root.tag.index('')] ET .register_namespace('', root.tag[1:root.tag.index('')]) 这不是保留已解析和输出 ElementTree 字符串差异的完整方法(如果使用 ElementTree.tostring(root))。歌唱完成了。【参考方案3】:在解析 xml 文件之前,您需要注册所有命名空间。
例如:如果您有这样的输入 xml Capabilities 是元素树的根。
<Capabilities xmlns="http://www.opengis.net/wmts/1.0"
xmlns:ows="http://www.opengis.net/ows/1.1"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:gml="http://www.opengis.net/gml"
xsi:schemaLocation="http://www.opengis.net/wmts/1.0 http://schemas.opengis.net/wmts/1.0/wmtsGetCapabilities_response.xsd"
version="1.0.0">
然后您必须像这样注册所有命名空间,即带有xmlns
的属性:
ET.register_namespace('', "http://www.opengis.net/wmts/1.0")
ET.register_namespace('ows', "http://www.opengis.net/ows/1.1")
ET.register_namespace('xlink', "http://www.w3.org/1999/xlink")
ET.register_namespace('xsi', "http://www.w3.org/2001/XMLSchema-instance")
ET.register_namespace('gml', "http://www.opengis.net/gml")
【讨论】:
这个答案是完整的。【参考方案4】:如果您尝试打印根目录,您将看到如下内容: http://www.host.domain/path/to/your/xml/namespaceRootTag' 在 0x0000000000558DB8>
因此,为了避免 ns0 前缀,您必须在解析 XML 数据之前更改默认命名空间,如下所示:
ET.register_namespace('', "http://www.host.domain/path/to/your/xml/namespace")
【讨论】:
以上是关于使用 ElementTree 保存 XML 文件的主要内容,如果未能解决你的问题,请参考以下文章
python解析xml文件之xml.etree.cElementTree和xml.etree.ElementTree区别
访问使用 ElementTree 解析的 xml 文件中的嵌套子项
如何让 Python 的 ElementTree 漂亮地打印到 XML 文件?