【问题标题】:Merging XML files with identical nodes using python使用python合并具有相同节点的XML文件
【发布时间】:2018-10-11 05:07:57
【问题描述】:

希望合并以下 XML。我想在 Python 中这样做,但无论如何这不是必需的。

文件 1:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
    <types> 
        <members>Class 1</members> 
        <members>Class 2</members>    
        <name>ApexClass</name>
    </types>
    <types>
        <members>Trigger 1</members>
        <name>ApexTrigger</name>
    </types>
    <types>
        <members>Rule 1</members>
        <members>Rule 2</members>
        <name>WorkflowRule</name>
    </types>   
    <types>
        <members>Address</members>
        <name>CustomField</name>
    </types>     
    <version>39.0</version>
</Package>

文件 2:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
    <types>
        <members>Class 3</members>  
        <name>ApexClass</name>
    </types>
    <types>
        <members>Rule 2</members>
        <name>WorkflowRule</name>
    </types>  
    <types>
        <members>Phone</members>
        <name>CustomField</name>
    </types>     
    <version>41.0</version>
</Package>

合并文件1文件2,在下面创建文件3

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
    <types>
        <members>Class 1</members> 
        <members>Class 2</members>    
        <members>Class 3</members>    
        <name>ApexClass</name>
    </types>
    <types>
        <members>Trigger 1</members>
        <name>ApexTrigger</name>
    </types>
    <types>
        <members>Rule 1</members>
        <members>Rule 2</members>
        <name>WorkflowRule</name>
    </types>  
    <types>
        <members>Address</members>
        <members>Phone</members>
        <name>CustomField</name>
    </types>     
    <version>41.0</version>
</Package>

请注意,标识节点可以是 50 多个不同的值之一。

提前感谢您的帮助。

编辑:哎呀,投反对票很痛。为了澄清和证明这个问题,我应该指出我什至很难从哪里开始解决这个问题,因为对 SO 的广泛搜索没有产生任何线索,问题的重点是获得关于从哪里开始的建议.

【问题讨论】:

  • 是的,您可以这样做。在 python 3.6 中,至少 xml 处理程序可以将整个文件读入一个不错的对象并复制到数组中,然后你可以很容易地组合数组。
  • @mpaler,请忽略这个问题的近距离投票和反对票。这个问题绝对没有错,投反对票的人有严重问题。当然,密切的原因(“太宽泛”)是无稽之谈。有人可能会批评这个问题,因为你没有展示你已经尝试过的东西,但在我看来,如果你不知道从哪里开始,问采取什么方法是完全合理的。
  • @MichaelKay 谢谢。我认为即使没有显示尝试将是针对 - 但是,你是对的,我什至不知道从哪里开始。也许我应该在问题中澄清这一点......

标签: python xml xslt merge salesforce


【解决方案1】:

既然您准备考虑替代 Python 编码,这里有一个 XSLT 3.0 解决方案:

<xsl:transform version="3.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="#all"
    xpath-default-namespace="http://soap.sforce.com/2006/04/metadata"
    expand-text="true">
    <xsl:param name="file1" as="xs:string"/>
    <xsl:param name="file2" as="xs:string"/>
    <xsl:template name="xsl:initial-template">
        <Package xmlns="http://soap.sforce.com/2006/04/metadata">
            <xsl:merge>
                <xsl:merge-source for-each-source="$file1, $file2"
                    select="//types" sort-before-merge="true">
                    <xsl:merge-key select="name"/>
                </xsl:merge-source>
                <xsl:merge-action>
                    <types>
                        <xsl:for-each-group select="current-merge-group()/members"
                            group-by=".">
                            <xsl:copy-of select="current-group()[1]"/>
                        </xsl:for-each-group>
                        <name>{current-merge-key()}</name>
                    </types>
                </xsl:merge-action>
            </xsl:merge>
        </Package>
    </xsl:template>
</xsl:transform>

您可以按如下方式从命令行运行它:

java net.sf.saxon.Transform -xsl:test.xsl -t -it file1=file1.xml file2=file2.xml !indent=yes

解释:xsl:merge-source 标识要合并的两个元素序列; xsl:merge-key 定义了它们要合并的键,并告诉我们序列尚未按该键排序。 xsl:merge-action 表示如何处理共享一个合并键的每组元素;在这种情况下,我们使用xsl:for-each-group 输出不同的&lt;members&gt; 元素,然后我们输出&lt;name&gt;

输出和您想要的输出之间有一个区别:样式表生成按&lt;name&gt; 排序的输出。我不确定您对输出进行排序的标准是什么;如果输出顺序很重要,那么我们可能需要调整。

【讨论】:

  • 感谢迈克尔!坦率地说,我从来没有意识到 xsl 是一个如此灵巧的工具。我将如何从命令行实现此解决方案?您能否建议一种将 for-each-source="doc('1.xml'), doc('2.xml')" 作为命令行参数传入的方法?
  • 下载 XSLT 3.0 处理器,如 Saxon-HE 并按照saxonica.com/documentation/index.html#!using-xsl/commandline 处的说明进行操作
  • 我已经修改了示例以将文件名声明为参数。如果需要,它也可以泛化为处理任意数量的输入文件。
  • 嗨迈克尔,今天试一试,我遇到了以下问题:xsl 中的静态错误:merge-key/@sort-before-merge on line 15 column 66 of stylesheet.xsl: XTSE0090 :元素 上不允许使用属性 @sort-before-merge 我应该指出我正在运行 OSX 版本的 saxon:来自 Saxonica 的 Saxon-HE 9.9.0.1J
  • 对不起,我把属性放在了错误的元素上:它属于 xsl:merge-source。既然你有兴趣使用它,我现在将测试这个例子。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-07-09
  • 1970-01-01
  • 1970-01-01
  • 2021-12-29
  • 2013-10-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多