【问题标题】:Merge two XMLs to produce a different XML output using XSLT使用 XSLT 合并两个 XML 以生成不同的 XML 输出
【发布时间】:2013-08-01 16:01:21
【问题描述】:

我一直在尝试编写 XSLT 以合并两个不同的 XML,并使用 XSLT v2.0 的 XSLT 代码生成不同的 XML 输出。

以下是我的要求。

输入 XML1 是这样的:

<?xml version="1.0" encoding="UTF-8"?>
<externalIdFields xmlns="urn:partner.soap.sforce.com/">
   <object name="Account">
      <ExternalID>
         <name>ExtAccountID__c</name>
         <type>string</type>
      </ExternalID>
   </object>
   <object name="User"/>
   <object name="Contact">
      <ExternalID>
         <name>ExtContactID__c</name>
         <type>string</type>
     </ExternalID>
   </object>
  <object name="Opportunity">
      <ExternalID>
        <name>ExtOpportunityID__c</name>
        <type>decimal</type>
     </ExternalID>
     <ExternalID>
        <name>UniqueAnotherOppID__c</name>
        <type>boolean</type>
     </ExternalID>
  </object>

而XML2是这样的:

<?xml version="1.0" encoding="UTF-8"?>
 <relationshipNames>
   <object name="Account">
      <reletionshipName>Parent</reletionshipName>
   </object>
   <object name="User">
      <reletionshipName>Owner</reletionshipName>
   </object>
   <object name="Contact">
     <reletionshipName>LookUpContact__r</reletionshipName>
   </object>
   <object name="Opportunity">
      <reletionshipName>LookUpOpportunity__r</reletionshipName>
   </object>
   <object name="Opportunity">
      <reletionshipName>AnotherRelationship__r</reletionshipName>
   </object>
</relationshipNames>

第一个 XML 包含每个对象的所有外部 ID,第二个 XML 包含每个对象的所有关系名称。

输出的 XML 应该是

<?xml version="1.0" encoding="UTF-8"?>
     <result xmlns:con = "http://www.approuter.com/schemas/cdk/config/">
       <con:field name = "Parent.ExtAccountID__c" label = "Parent.ExtAccountID__c">
         <con:type>string</con:type>
      </con:field>
      <con:field name = "LookUpContact__r.ExtContactID__c" label="LookUpContact__r.ExtContactID__c">
         <con:type>string</con:type>
      </con:field>
      <con:field name = "LookUpOpportunity__r.ExtOpportunityID__c" label = "LookUpOpportunity__r.ExtOpportunityID__c">
           <con:type>decimal</con:type>
      </con:field>
      <con:field name = "LookUpOpportunity__r.UniqueAnotherOppID__c." label = "LookUpOpportunity__r.UniqueAnotherOppID__c">
           <con:type>boolean</con:type>
      </con:field>
      <con:field name = "AnotherRelationship__r.ExtOpportunityID__c." label = "AnotherRelationship__r.ExtOpportunityID__c">
           <con:type>boolean</con:type>
       </con:field>
       <con:field name = "AnotherRelationship__r.UniqueAnotherOppID__c." label = "AnotherRelationship__r.UniqueAnotherOppID__c">
           <con:type>boolean</con:type>
       </con:field>
  </result>

合并很简单。对于每个对象的每个 externalId,创建一个 con:field 标记,这里 name 和 label 的值应该是该对象的对应 relationshipName 和 externalId 字段名称。它将是relationshiName.externalIdFieldName。对象的 relationshipName 应仅与该对象的 externalIds 相关联。

我们怎样才能做到这一点?我看到了一个 XSLT 来合并两个 XML。但我不理解不同示例的“@* | node()”部分。在这里,我没有找到解析两个完全不同的 XML 的示例。

感谢您的帮助。

【问题讨论】:

    标签: xml merge xslt-2.0


    【解决方案1】:

    这是我的建议:

    <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
      xmlns:sf="urn:partner.soap.sforce.com/"
      xmlns:con="http://www.approuter.com/schemas/cdk/config/"
      exclude-result-prefixes="sf">
    
    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>
    
    <xsl:param name="names-url" select="'test2013080105.xml'"/>
    <xsl:variable name="names-doc" select="doc($names-url)"/>
    
    <xsl:key name="name" match="relationshipNames/object" use="@name"/>
    
    <xsl:template match="sf:externalIdFields">
      <result>
        <xsl:apply-templates/>
      </result>
    </xsl:template>
    
    <xsl:template match="sf:object/sf:ExternalID">
      <xsl:apply-templates select="key('name', ../@name, $names-doc)">
        <xsl:with-param name="eid" select="current()"/>
      </xsl:apply-templates>
    </xsl:template>
    
    <xsl:template match="relationshipNames/object">
      <xsl:param name="eid"/>
      <con:field name="{reletionshipName}.{$eid/sf:name}" label="{reletionshipName}.{$eid/sf:name}">
        <con:type><xsl:value-of select="$eid/sf:type"/></con:type>
      </con:field>
    </xsl:template>
    
    </xsl:stylesheet>
    

    样式表采用参数names-url 作为第二个文件名/U​​RL。还要确保所有元素名称和命名空间 URL 都已发布(即reletionshipName),或者如果实际输入具有正确拼写的元素名称,请确保编辑样式表以具有正确的拼写,例如 relationshipName

    【讨论】:

    • 嗨,马丁。非常感谢你的帮助。它工作得很好。很大的帮助。优秀的 XSLT。但是,在合并的同时,是否也可以将一个 XML 附加到另一个 XML 上?
    • 通常你想创建格式良好的文档,如果你只是追加你会得到两个根元素,然后它们不是格式良好的。但是你当然可以写&lt;xsl:template match="/*"&gt;&lt;xsl:copy&gt;&lt;xsl:copy-of select="node(), doc('file2.xml')/*/node()"/&gt;&lt;/xsl:copy&gt;&lt;/xsl:template&gt;来保留主输入的根元素并复制第二个输入的根元素的所有子节点。
    • 嗨,Martin,我注意到如果 xml2 包含另一个名称为 Opportunity&lt;object&gt; 标记,则 XSLT 无法提供正确的输出。在这种情况下,输出应包含另外 2 个 &lt;con:field&gt; 标记,用于 2 个 Opportunities externalIds 的新 relationshipName。对修改上述 XSLT 代码有何建议?
    • @RaghavendraNilekani,我已更改代码以确保每个引用的 object 都会创建一些输出。我认为现在该示例为编辑后的示例输入文档生成了您想要的输出数量和类型,尽管输出元素的顺序与您发布的不同。检查结果是否适合您,如果不适合,请解释定义输出顺序的内容。
    猜你喜欢
    • 1970-01-01
    • 2019-08-25
    • 1970-01-01
    • 2013-10-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多