在Python

时间:2017-11-19 12:08:26

标签: python xml xslt

我在目录中有100个xml文件。 xml的结构完全相同。但是,我想将xml的一些节点添加到一起并保留其余部分。

示例xml 1

<?xml-stylesheet type='text/xsl' href='image_metadata_stylesheet.xsl'?>
<dataset>
<name>imglab dataset</name>
<comment>Created by imglab tool.</comment>
<images>
<image file='/home/orcl/user102339/Area123/Geo_Tag_0812-0420.jpg'></image>
<image file='/home/orcl/user102339/Area123/Geo_Tag_0812-0544.jpg'>
<box top='343' left='72' width='92' height='29'>
<label>LBS_Marks
</label></box></image>
<image file='/home/orcl/user102339/Area123/Geo_Tag_0812-0489.jpg'></image>
</images>
</dataset>

示例xml 2

<?xml-stylesheet type='text/xsl' href='image_metadata_stylesheet.xsl'?>
<dataset>
<name>imglab dataset</name>
<comment>Created by imglab tool.</comment>
<images>
<image file="/home/orcl/user102339/Area123/Geo_Tag_0812-0420.jpg">
    <box top="505" left="326" width="59" height="32">
                <label>SBS_Marks</label>
            </box>
    </image>
<image file="/home/orcl/user102339/Area123/Geo_Tag_0812-0544.jpg">
    <box top="507" left="331" width="50" height="27">
                <label>SBS_Marks</label>
            </box>
    </image>
<image file="/home/orcl/user102339/Area123/Geo_Tag_0812-0489.jpg">
    <box top="509" left="330" width="51" height="25">
                <label>SBS_Marks</label>
            </box>
    </image>
</images>
</dataset>

在这两个数据集中,图像是相同的,但标记是不同的。例如,在第一个示例集中,第一个图像0420.jpg没有与之关联的任何框标签,而第二个文件中的相同图像具有与之关联的标签SBS_Marks的框标签。我试图将这些文件合并在一起,这样对于每个图像,我只得到框坐标和标签。例如,所需的输出如下:

<?xml-stylesheet type='text/xsl' href='image_metadata_stylesheet.xsl'?>
<dataset>
<name>imglab dataset</name>
<comment>Created by imglab tool.</comment>
<images>
<image file='/home/orcl/user102339/Area123/Geo_Tag_0812-0420.jpg'>
<box top="505" left="326" width="59" height="32">
                <label>SBS_Marks</label>
            </box>
</image>
<image file='/home/orcl/user102339/Area123/Geo_Tag_0812-0544.jpg'>
<box top='343' left='72' width='92' height='29'>
<label>LBS_Marks
</label></box>
<box top="507" left="331" width="50" height="27">
                <label>SBS_Marks</label>
            </box>
</image>
<image file='/home/orcl/user102339/Area123/Geo_Tag_0812-0489.jpg'>
<box top="509" left="330" width="51" height="25">
                <label>SBS_Marks</label>
            </box>

</image>
</images>
</dataset>

在所需的输出示例中,第一个图像0420.jpg具有来自第二个文件的框和标签元素,第二个图像0544.jpg具有两个框,并且标签分别来自文件1和文件2,第三个图像具有框和第二个文件中的标签。

我尝试使用此代码:

#!/usr/bin/env python
import sys
from xml.etree import ElementTree

def run(files):
    first = None
    for filename in files:
        data = ElementTree.parse(filename).getroot()
        if first is None:
            first = data
        else:
            first.extend(data)
    if first is not None:
        print ElementTree.tostring(first)

if __name__ == "__main__":
    run(sys.argv[1:])

但这只是一个接一个地打印文件的内容但不合并。我不知道如何创建xsl模板,因此无法尝试使用它。有人可以为上面的代码提供更好的代码,或者提供一个xsl模板,帮助我合并文件夹中的所有这些文件。

1 个答案:

答案 0 :(得分:1)

如果您仅限于XSLT 1,那么我认为一种方法是使用Python构建一个XML文档,列出您要合并的目录的所有XML文件,例如:格式为

<files>
  <file name="doc1.xml"/>
  <file name="doc2.xml"/>
  ...
</files>

然后您将该文件用作XSLT的输入文档并将代码编写为

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">

    <xsl:strip-space elements="*"/>
    <xsl:output indent="yes"/>

    <xsl:variable name="files" select="document(files/file/@name)"/>

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

    <xsl:template match="/">
        <xsl:apply-templates select="$files[1]/node()"/>
    </xsl:template>

    <xsl:template match="image[@file]">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
            <xsl:apply-templates select="$files[position() > 1]//image[@file = current()/@file]/node()"/>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

当然,如果您要合并数百个文件,那么document(files/file/@name)会将它们全部存入内存,但如果您想将它们全部合并到一个转换中,我看不到任何方法。