将命名空间放入Python中的不同XML标签

时间:2019-05-24 14:42:56

标签: python xml xml-namespaces elementtree

我在tmp/Program.ev3p中有一个xml文件:

<?xml version="1.0" encoding="utf-8"?>
<SourceFile Version="1.0.2.10" xmlns="http://www.ni.com/SourceModel.xsd">
    <Namespace Name="Project">
        <VirtualInstrument IsTopLevel="false" IsReentrant="false" Version="1.0.2.0" OverridingModelDefinitionType="X3VIDocument" xmlns="http://www.ni.com/VirtualInstrument.xsd">
            <FrontPanel>
                <fpruntime:FrontPanelCanvas xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:fpruntime="clr-namespace:NationalInstruments.LabVIEW.FrontPanelRuntime;assembly=NationalInstruments.LabVIEW.FrontPanelRuntime" xmlns:Model="clr-namespace:NationalInstruments.SourceModel.Designer;assembly=NationalInstruments.SourceModel" x:Name="FrontPanel" Model:DesignerSurfaceProperties.CanSnapToObjects="True" Model:DesignerSurfaceProperties.SnapToObjects="True" Model:DesignerSurfaceProperties.ShowSnaplines="True" Model:DesignerSurfaceProperties.ShowControlAdorners="True" Width="640" Height="480" />
            </FrontPanel>
            <BlockDiagram Name="__RootDiagram__">
                <StartBlock Id="n1" Bounds="0 0 70 91" Target="X3\.Lib:StartBlockTest">
                    <ConfigurableMethodTerminal>
                        <Terminal Id="Result" Direction="Output" DataType="Boolean" Hotspot="0.5 1" Bounds="0 0 0 0" />
                    </ConfigurableMethodTerminal>
                    <Terminal Id="SequenceOut" Direction="Output" DataType="NationalInstruments:SourceModel:DataTypes:X3SequenceWireDataType" Hotspot="1 0.5" Bounds="52 33 18 18" />
                </StartBlock>
            </BlockDiagram>
        </VirtualInstrument>
    </Namespace>
</SourceFile>

我正在尝试使用以下代码对其进行修改:

import xml.etree.ElementTree as ET

tree = ET.parse('tmp/Program.ev3p')
root = tree.getroot()

namespaces = {'http://www.ni.com/SourceModel.xsd': '' ,
              'http://www.ni.com/VirtualInstrument.xsd':'',
              'http://schemas.microsoft.com/winfx/2006/xaml/presentation':'',
              'http://schemas.microsoft.com/winfx/2006/xaml':'x',
              'clr-namespace:NationalInstruments.LabVIEW.FrontPanelRuntime;assembly=NationalInstruments.LabVIEW.FrontPanelRuntime':'fpruntime',
              'clr-namespace:NationalInstruments.SourceModel.Designer;assembly=NationalInstruments.SourceModel': 'Model',
              }

for uri, prefix in namespaces.items():
    ET._namespace_map[uri] = prefix

diagram = root[0][0][1]
elem = ET.Element('Data')
diagram.append(elem)

tree.write('tmp/Program.ev3p',"UTF-8",xml_declaration=True)

运行代码后,我的xml文件包含:

<?xml version='1.0' encoding='UTF-8'?>
<SourceFile xmlns="http://www.ni.com/SourceModel.xsd" xmlns="http://www.ni.com/VirtualInstrument.xsd" xmlns:Model="clr-namespace:NationalInstruments.SourceModel.Designer;assembly=NationalInstruments.SourceModel" xmlns:fpruntime="clr-namespace:NationalInstruments.LabVIEW.FrontPanelRuntime;assembly=NationalInstruments.LabVIEW.FrontPanelRuntime" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Version="1.0.2.10">
    <Namespace Name="Project">
        <VirtualInstrument IsReentrant="false" IsTopLevel="false" OverridingModelDefinitionType="X3VIDocument" Version="1.0.2.0">
            <FrontPanel>
                <fpruntime:FrontPanelCanvas Height="480" Width="640" Model:DesignerSurfaceProperties.CanSnapToObjects="True" Model:DesignerSurfaceProperties.ShowControlAdorners="True" Model:DesignerSurfaceProperties.ShowSnaplines="True" Model:DesignerSurfaceProperties.SnapToObjects="True" x:Name="FrontPanel" />
            </FrontPanel>
            <BlockDiagram Name="__RootDiagram__">
                <StartBlock Bounds="0 0 70 91" Id="n1" Target="X3\.Lib:StartBlockTest">
                    <ConfigurableMethodTerminal>
                        <Terminal Bounds="0 0 0 0" DataType="Boolean" Direction="Output" Hotspot="0.5 1" Id="Result" />
                    </ConfigurableMethodTerminal>
                    <Terminal Bounds="52 33 18 18" DataType="NationalInstruments:SourceModel:DataTypes:X3SequenceWireDataType" Direction="Output" Hotspot="1 0.5" Id="SequenceOut" />
                </StartBlock>
            <Data /></BlockDiagram>
        </VirtualInstrument>
    </Namespace>
</SourceFile>

我需要将名称空间包含在它们在原始文件中注册的标记中,而不是将所有名称空间包含在SourceFile中,是否可以在python中实现?

1 个答案:

答案 0 :(得分:1)

当前,未记录的ElementTree._namespace_map[uri] = prefix是较旧的Python版本(<1.3),用于将命名空间分配给更新的,已记录的ElementTree.register_namespace(prefix, uri)。但是,即使此方法也无法解决根本问题,文档强调此分配在全球范围内适用,并替换了以前的任何名称空间或前缀:

  

xml.etree.ElementTree.register_namespace(前缀,uri)
  注册名称空间前缀。注册表是全局的,并且任何现有的   给定前缀或名称空间URI的映射将是   删除。 prefix 是名称空间前缀。 uri 是命名空间uri。标签   并且此命名空间中的属性将使用给定的序列化   前缀(如果可能)。


要获得所需的结果,并且由于XML带有多个默认名称空间和非默认名称空间,因此有点复杂,请考虑使用XSLT(一种用于转换XML文件的专用语言)。 Python可以使用第三方模块lxml(不是内置的etree)运行XSLT 1.0脚本。此外,XSLT具有可移植性,因此代码可以在其他语言(Java,C#,PHP,VB)和专用的processors(例如,Saxon,Xalan)中运行。

具体来说,您可以使用诸如 doc 之类的临时前缀来映射最低级别父级 VirtualInstrument 的默认名称空间,并使用该前缀来标识所需的节点。使用identity transform模板复制所有其他元素。另外,由于您要向默认名称空间添加元素,因此可以使用xsl:element标签对其进行分配。

XSLT (以下另存为.xsl文件,一个特殊的.xml文件)

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                              xmlns:doc="http://www.ni.com/VirtualInstrument.xsd">
  <xsl:output indent="yes"/>
  <xsl:strip-space elements="*"/>

  <!-- IDENTITY TRANSFORM -->
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="doc:BlockDiagram">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
      <xsl:element name="Data" namespace="http://www.ni.com/VirtualInstrument.xsd"/>      
    </xsl:copy>
  </xsl:template>    

</xsl:stylesheet>

Python

import lxml.etree as ET

# LOAD XML AND XSL 
dom = ET.parse('Input.xml')
xslt = ET.parse('XSLTScript.xsl')

# TRANSFORM INPUT
transform = ET.XSLT(xslt)
newdom = transform(dom)

# OUTPUT RESULT TREE TO CONSOLE
print(newdom) 

# SAVE RESULT TREE AS XML
with open('Output.xml','wb') as f:
     f.write(newdom)

XSLT Demo