试图合并以下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的广泛搜索没有任何线索,因此我很难确定从哪里开始这个问题,并且问题的重点是从何处开始获得建议
答案 0 :(得分: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
表示如何处理共享合并键的每组元素;在这种情况下,我们使用<members>
输出不同的xsl:for-each-group
元素,然后输出<name>
。
输出与所需输出之间有一个区别:样式表生成按<name>
排序的输出。我不确定您对输出进行排序的标准;如果输出顺序很重要,那么我们可能需要进行调整。