【问题标题】:Parse Two XML using Python使用 Python 解析两个 XML
【发布时间】:2015-12-16 06:53:54
【问题描述】:

我有一个包含 200 个 Event 块的 XML 文件,如下所示:

<?xml version='1.0' encoding='UTF-8'?>
<ProjectData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.project.com/proj1/projv" xsi:schemaLocation="http://www.pp.com/oj/p http://www.onj.com/p/IXX/schema/proj.xsd">
  <fileType>This file is sample</fileType>
  <header>
    <fileID>none</fileID>
    <version>1.0</version>
    <modified>2015-09-16T17:03:25</modified>
  </header>
  <EventList>
    <Event>
      <Id>0</Id>
      <pp define="something">2</pp>
      <Index>3</Index>
      <Conf ref="point">CFG.AC.UF</Conf>
      <Check>tttt</Check>
      <Group>wwll</Group>
      <Heart ref="point">mbmb</Heart>
      <Name>kkk</Name>
      <Thresh ref="point">kckcv</Thresh>
      <Hyster ref="point">foo</Hyster>
      <Trip ref="point">dim</Trip>
      <Clear ref="point">CLR.AC.UF</Clear>
    </Event>
  </EventList>
</ProjData>

Event 块包含我有兴趣获取的信息(仅其中 4 个:Id、Index、Name 和 Group)来生成我的新 xml 文件。我想通过python代码来做到这一点。 有谁知道我如何通过 python 实现这一点。

我的新 xml 文件应该如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<Newevents>
   <event>
      <Id>0</Id>
      <Index>3</Index>
      <Name>kkk**$Id**</Name>
      <Group>wwll**$Index**</Group>
      <desc>placeholder</desc>
   </event>
</Newevents>

我还想添加 ID 和索引,它们是数字来命名并使用三位有效数字占位符对字符串进行分组。 例如,如果 Id 是 1,我希望我的名字是 kkk001,或者如果 Id 是 3,我希望我的名字是 kkk003。 我的组元素字符串相同,但使用索引:如果索引为 5,我希望我的组为 wwll005。

我在 Google 上搜索过,但关于此的零星信息。

  1. 谁能想出一个简洁的 python 代码来解析我的 xml 文件并以我想要的格式和编号生成新的 xml 文件?

  2. 我有另一个名为 descXML.xml 的 xml 文件,我需要对其进行解析以仅获取 desc 元素字符串并将其添加到我的 new xml 文件中。 在我拥有的第二个 xml 文件 (descXML.xml) 中,应该根据与我的新 xml 文件匹配的 Id 获取 desc 元素数据。 是否有可能检查 Id 元素是否等于我的新 xml 文件的 Id 元素数据,然后添加 desc 元素内容对应的代号?我该怎么做这个条件?你能为此提供python示例吗?

这是 descXML.xml 文件的外观,类似于我的第一个原始 xml 文件,这里也是 200 个 Event 块:

<EventList>
  <Event>
    <Mnemonic>AC.UF.SLOW</Mnemonic>
    <Id define="xyz">3</Id>
    <Index>13</Index>
    <Description>today was warm and I want to go swimming</Description>
  </Event>
<EventList>

上面的1和2可以合并成一个python文件吗?

我想要的最终 XML 文件应该如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<Newevents>
   <event>
      <Id>3</Id>
      <Index>13</Index>
      <Name>kkk000</Name>
      <Group>wwll003</Group>
      <desc>today was warm and I want to go swimming</desc>
   </event>

基于下面给出的 cmets 进行试验:

我试图在这里简洁并尝试下面提供的解决方案但没有奏效,所以我提供了我的确切 xml 文件:

我的文件 1.xml

<?xml version='1.0' encoding='UTF-8'?>
<Dataizx xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.kklk.com/cx1/ASD" xsi:schemaLocation="http://www.kklk.com/cx1/ASD http://www.kklk.com/cx1/ASD/schema/tell.xsd">
  <fileType>Auto-Generated IXX Events Metadata</fileType>
  <header>
    <fileID>none</fileID>
    <version>1.0</version>
    <modified>2015-09-16T17:03:25</modified>
  </header>
  <EventList>
    <Event>
      <Mnemonic>ijk</Mnemonic>
      <Id define="rece">2</Id>
      <Index>0</Index>
      <Config ref="point">shine</Config>
    </Event>
    <Event>
      <Mnem>xyz</Mnem>
      <Id define="teller">3</Id>
      <Index>1</Index>
      <Config ref="point">good</Config>
    </Event>
  </EventList>
</Dataizx>

这是我的包含描述的 xml:

<?xml version="1.0" encoding="UTF-8"?>
<IXXData xmlns="http://www.mnm.com/mnm/mnm" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:i="http://www.mnm.com/mnm/mnm" xsi:schemaLocation="http://www.mnm.com/mnm/mnm http://www.mnm.com/mnm/mnm/schema/mnm.xsd">
    <fileType>Merged IXX Events Metadata</fileType>
    <header>
        <fileID>none</fileID>
        <version>1.0 + none</version>
        <description>Merged event metadata.</description>
    </header>
    <EventList>
        <Event>
            <Id define="mmm">2</Id>
            <Description>everything was good.</Description>
        </Event>
        <Event>
            <Id define="lll">4</Id>
            <Description>teller and the other one.</Description>
        </Event>
        <Event>
            <Id define="ggg">3</Id>
            <Description>weather is nice.</Description>
        </Event>
    </EventList>
</IXXData>

我使用了你的 xsl 和 python,但我无法从第二个文件中得到描述。

【问题讨论】:

    标签: python xml xml-parsing automation code-generation


    【解决方案1】:

    考虑一个 XLST 解决方案,它可以从原始 XML 中挑选各种节点,并根据特定标准在外部 XML 中合并节点。 Python(像许多面向对象的编程语言一样)在其 lxml 模块中维护XSLT processor

    作为信息,XSLT 是一种特殊用途的声明性编程语言(不是面向对象的语言),用于将 XML 文件转换为各种格式和结构。

    此外,您还可以使用 XSLT 的 document()concat() 函数。您的 XSLT 有点复杂,因为它需要设置一个变量来匹配文档中的 id,并且需要管理大量的命名空间。

    XSLT(外部保存为 .xsl 文件)

    <xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xmlns:p="http://www.kklk.com/cx1/ASD"
     xmlns:i="http://www.sesolar.com/SE1/ICB"
     xsi:schemaLocation="http://www.kklk.com/cx1/ASD http://www.kklk.com/cx1/ASD/schema/tell.xsd"
     exclude-result-prefixes="xsi p i">
    
    <xsl:output version="1.0" encoding="UTF-8"/>
    
    <xsl:template match="p:EventList">
        <NewsEvents>        
            <xsl:for-each select="p:Event">            
                <Id><xsl:value-of select="p:Id"/></Id>
                <Index><xsl:value-of select="p:Index"/></Index>
                <Name><xsl:value-of select="concat(p:Name, '00', p:Id)"/></Name>
                <Group><xsl:value-of select="concat(p:Group, '00', p:Index)"/></Group>
                <xsl:variable name="descID" select="p:Id"/>
                <desc><xsl:value-of select="document('descXML.xml')/i:IcbData/i:EventList/
                      i:Event/i:Id[text()=$descID]/following-sibling::i:Description"/></desc>            
            </xsl:for-each>
        </NewsEvents>
    </xsl:template>
    
    </xsl:transform>
    

    Python(加载 .xml 和 .xsl,将前者与后者转换为新的 .xml 输出)

    #!/usr/bin/python
    import lxml.etree as ET
    
    dom = ET.parse('C:\\Path\\To\\MainXML.xml')
    xslt = ET.parse('C:\\Path\\To\\AboveXSLT.xsl')
    transform = ET.XSLT(xslt)
    newdom = transform(dom)
    
    tree_out = ET.tostring(newdom, encoding='UTF-8', pretty_print=True, xml_declaration=True)
    
    xmlfile = open('C:\\Path\\To\\Output.xml','wb')
    xmlfile.write(tree_out)
    xmlfile.close()
    

    输出(使用上面发布的 XML 数据)

    (如果 descXML 的 Id 与任何 Event 的 Id 匹配,则将填充下面对应的 &lt;desc&gt; 节点)

    <?xml version='1.0' encoding='UTF-8'?>
    <Dataroot>
      <NewsEvents>
        <Id>2</Id>
        <Index>0</Index>
        <Name>002</Name>
        <Group>000</Group>
        <desc>everything was good.</desc>
      </NewsEvents>
      <NewsEvents>
        <Id>3</Id>
        <Index>1</Index>
        <Name>003</Name>
        <Group>001</Group>
        <desc>weather is nice.</desc>
      </NewsEvents>
    </Dataroot>
    

    我知道这种 XSLT 方法可能看起来很吓人,但它可以节省大量循环并在 Python 代码中创建元素、子元素和属性。每当处理 XML 文件时,我经常推荐这条路线,而且我确实发现它在程序员中被忽略了,而不仅仅是 Python 爱好者。同时,毫无疑问,最容易使用另一种特殊用途的声明性语言 -SQL

    【讨论】:

    • 谢谢。但是为什么没有填写描述字段? xsl 中描述的逻辑是否正确?
    • 我认为description一直为空的原因是因为我们没有搜索整个descXML.xml文件。该文件是我的第二个 xml 文件,其中包含每个 Event 块的描述,但由于此 xml 文件中的事件不按顺序排列,它不会在我的最终输出中填写任何内容!这是真的?还是有其他原因?
    • 您发布的 XML 内容中的 ID 不匹配。在 descXML Id = 3 和 Event XML Id=0 中。此外,顺序无关紧要,XSLT 在每个 Event 节点上运行 for-each 循环,并且每次都匹配 descXML 的 Id。
    • 您的解决方案很有帮助,但我想我在这里遗漏了一些东西。我在上面发布了我的两个 xml 文件,这次我的 ID 是正确的。最初,正如我所提到的,我有 200 个事件块,并且我期望匹配一些描述。
    • 你可以试试我的第二次试验,如果你得到结果,请告诉我?我有两个匹配的 ID。请查看“基于下面给出的 cmets 的试用”部分:
    猜你喜欢
    • 2014-01-20
    • 2021-02-06
    • 2017-08-31
    • 2014-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多