【发布时间】:2018-06-21 15:48:44
【问题描述】:
我有大量的 XML 文件,我想在其中进行以下更改:
创建一个新元素——我们称之为
new_element——在根元素下找到另一个嵌套更深的特定元素——我们称之为
existing_element——并移动它,使其成为new_element的子元素
我想以尽可能少的干扰方式来做到这一点,这样旧文件和新文件之间的差异只显示属于新创建元素的行的更改(因此已添加到文件中)或曾经属于被移动的元素(因此已从文件中删除)。我想使用 Python 3 来做到这一点。
但是,当我尝试使用 xml.dom.minidom 读取其中一个 XML 文件并将刚刚读取的内容写入一个新文件并比较这两个文件时,每一行都被标记为已更改(可能是因为它们包含不同类型的换行符)。此外,当我查看这两个文件的内容时,我发现 XML 声明中的编码规范以及声明后的换行符都消失了,并且整个文档中的标签中的属性都被打乱了顺序标签。
使用xml.etree.ElementTree 时的情况非常相似,只是现在整个 XML 声明都消失了,所有标签名称前面都有“ns0:”(出于某种原因),一些属性名称后面是“@987654327 @"。
这些对 XML 文件的“额外”修改都是不可取的,因为我希望能够区分旧文件和新文件,并且能够轻松查看哪些已更改,哪些未更改。
那么,有没有一些简单的方法可以基于另一个 XML 文件创建一个新的 XML 文件,该文件只对真正应该更改的行进行更改,而所有其他行都保持不变,并且不涉及编写自己的代码来解析 XML 数据?
编辑:这是我要处理的文件的结构(因为我不知道什么会导致任何建议的代码工作或不工作与我的 XML 文件,我只有删除了存储在文件中三个不同位置的数据——我已将其替换为“*data*”——并保持其他所有内容不变):
<?xml version="1.0" encoding="UTF-8"?>
<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1">
<asset>
<contributor/>
<created>2017-01-23T12:01:30Z</created>
<modified>2017-01-23T12:01:30Z</modified>
<unit/>
<up_axis>Z_UP</up_axis>
</asset>
<library_visual_scenes>
<visual_scene id="defaultScene">
<node id="sceneRoot">
<instance_geometry url="#geometry">
<bind_material>
<technique_common>
<instance_material symbol="geometry_material" target="#material">
<bind_vertex_input semantic="texcoord0" input_semantic="TEXCOORD" input_set="0"/>
</instance_material>
</technique_common>
</bind_material>
</instance_geometry>
</node>
</visual_scene>
</library_visual_scenes>
<library_geometries>
<geometry id="geometry">
<mesh>
<source id="geometry-positions">
<float_array id="geometry-positions-array" count="673731">*data*</float_array>
<technique_common>
<accessor count="224577" source="#geometry-positions-array" stride="3">
<param name="X" type="float"/>
<param name="Y" type="float"/>
<param name="Z" type="float"/>
</accessor>
</technique_common>
</source>
<source id="geometry-texcoord_0">
<float_array id="geometry-texcoord_0-array" count="449154">*data*</float_array>
<technique_common>
<accessor count="224577" source="#geometry-texcoord_0-array" stride="2">
<param name="S" type="float"/>
<param name="T" type="float"/>
</accessor>
</technique_common>
</source>
<vertices id="geometry-vertices">
<input semantic="POSITION" source="#geometry-positions"/>
</vertices>
<triangles count="329753" material="geometry_material">
<input offset="0" semantic="VERTEX" source="#geometry-vertices" set="0"/>
<input offset="1" semantic="TEXCOORD" source="#geometry-texcoord_0" set="0"/>
<p>*data*</p>
</triangles>
</mesh>
</geometry>
</library_geometries>
<library_materials>
<material id="material">
<instance_effect url="#material_effect"/>
</material>
</library_materials>
<library_effects>
<effect id="material_effect">
<profile_COMMON>
<image id="material_effect-image" height="0" width="0">
<init_from>Tile_+037_+047_0.jpg</init_from>
</image>
<newparam sid="material_effect-surface">
<surface type="2D">
<init_from>material_effect-image</init_from>
</surface>
</newparam>
<newparam sid="material_effect-sampler">
<sampler2D>
<source>material_effect-surface</source>
<wrap_s>CLAMP</wrap_s>
<wrap_t>CLAMP</wrap_t>
<minfilter>LINEAR_MIPMAP_LINEAR</minfilter>
<magfilter>LINEAR</magfilter>
<border_color>0 0 0 0</border_color>
</sampler2D>
</newparam>
<technique sid="t0">
<phong>
<emission>
<color>0 0 0 1</color>
</emission>
<ambient>
<color>1 1 1 1</color>
</ambient>
<diffuse>
<texture texture="material_effect-sampler" texcoord="texcoord0">
<extra type="color">
<technique profile="SCEI">
<color>1 1 1 1</color>
</technique>
</extra>
</texture>
</diffuse>
<specular>
<color>0 0 0 1</color>
</specular>
<shininess>
<float>0</float>
</shininess>
</phong>
</technique>
</profile_COMMON>
</effect>
</library_effects>
<scene>
<instance_visual_scene url="#defaultScene"/>
</scene>
</COLLADA>
这就是我希望 XML 变成的内容:
<?xml version="1.0" encoding="UTF-8"?>
<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1">
<asset>
<contributor/>
<created>2017-01-23T12:01:30Z</created>
<modified>2017-01-23T12:01:30Z</modified>
<unit/>
<up_axis>Z_UP</up_axis>
</asset>
<library_visual_scenes>
<visual_scene id="defaultScene">
<node id="sceneRoot">
<instance_geometry url="#geometry">
<bind_material>
<technique_common>
<instance_material symbol="geometry_material" target="#material">
<bind_vertex_input semantic="texcoord0" input_semantic="TEXCOORD" input_set="0"/>
</instance_material>
</technique_common>
</bind_material>
</instance_geometry>
</node>
</visual_scene>
</library_visual_scenes>
<library_geometries>
<geometry id="geometry">
<mesh>
<source id="geometry-positions">
<float_array id="geometry-positions-array" count="673731">*data*</float_array>
<technique_common>
<accessor count="224577" source="#geometry-positions-array" stride="3">
<param name="X" type="float"/>
<param name="Y" type="float"/>
<param name="Z" type="float"/>
</accessor>
</technique_common>
</source>
<source id="geometry-texcoord_0">
<float_array id="geometry-texcoord_0-array" count="449154">*data*</float_array>
<technique_common>
<accessor count="224577" source="#geometry-texcoord_0-array" stride="2">
<param name="S" type="float"/>
<param name="T" type="float"/>
</accessor>
</technique_common>
</source>
<vertices id="geometry-vertices">
<input semantic="POSITION" source="#geometry-positions"/>
</vertices>
<triangles count="329753" material="geometry_material">
<input offset="0" semantic="VERTEX" source="#geometry-vertices" set="0"/>
<input offset="1" semantic="TEXCOORD" source="#geometry-texcoord_0" set="0"/>
<p>*data*</p>
</triangles>
</mesh>
</geometry>
</library_geometries>
<library_materials>
<material id="material">
<instance_effect url="#material_effect"/>
</material>
</library_materials>
<library_effects>
<effect id="material_effect">
<profile_COMMON>
<newparam sid="material_effect-surface">
<surface type="2D">
<init_from>material_effect-image</init_from>
</surface>
</newparam>
<newparam sid="material_effect-sampler">
<sampler2D>
<source>material_effect-surface</source>
<wrap_s>CLAMP</wrap_s>
<wrap_t>CLAMP</wrap_t>
<minfilter>LINEAR_MIPMAP_LINEAR</minfilter>
<magfilter>LINEAR</magfilter>
<border_color>0 0 0 0</border_color>
</sampler2D>
</newparam>
<technique sid="t0">
<phong>
<emission>
<color>0 0 0 1</color>
</emission>
<ambient>
<color>1 1 1 1</color>
</ambient>
<diffuse>
<texture texture="material_effect-sampler" texcoord="texcoord0">
<extra type="color">
<technique profile="SCEI">
<color>1 1 1 1</color>
</technique>
</extra>
</texture>
</diffuse>
<specular>
<color>0 0 0 1</color>
</specular>
<shininess>
<float>0</float>
</shininess>
</phong>
</technique>
</profile_COMMON>
</effect>
</library_effects>
<scene>
<instance_visual_scene url="#defaultScene"/>
</scene>
<library_images>
<image id="material_effect-image" height="0" width="0">
<init_from>Tile_+037_+047_0.jpg</init_from>
</image>
</library_images>
</COLLADA>
注意在第二段 XML 中,如何在根元素下创建了一个名为 library_images 的标记(根元素下不重要,只要它是它的直接子元素),并且该元素image 已移入其中。
【问题讨论】:
标签: python xml xml-parsing elementtree minidom