【问题标题】:Putting Namespaces into Different XML Tags in Python在 Python 中将命名空间放入不同的 XML 标记中
【发布时间】:2019-05-24 14:42:55
【问题描述】:

我在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 中实现?

【问题讨论】:

    标签: python xml xml-namespaces elementtree


    【解决方案1】:

    目前,未记录的 ElementTree._namespace_map[uri] = prefix 是较旧的 Python 版本 (ElementTree.register_namespace(prefix, uri)。但即使这种方法也不能解决根本问题,文档强调此分配适用于全局并替换任何先前的命名空间或前缀:

    xml.etree.ElementTree.register_namespace(prefix, 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

    【讨论】:

      猜你喜欢
      • 2011-10-11
      • 1970-01-01
      • 2022-10-04
      • 2014-04-19
      • 2020-10-13
      • 2021-10-03
      • 1970-01-01
      • 1970-01-01
      • 2014-02-15
      相关资源
      最近更新 更多