【问题标题】:how to merge 2 xml files into one based on matching node by xslt如何通过xslt基于匹配节点将2个xml文件合并为一个
【发布时间】:2021-07-16 07:57:17
【问题描述】:

我有 2 个 xml 文件,要求通过匹配节点将两个文件合并为一个。以下是文件。

第一个 XML 是(原始的):

    <EF_Candidate_List>
    <EF_Candidate>
    <candidate_id>1</candidate_id>
    <field_1>foo</field_1>
    </EF_Candidate>
    <EF_Candidate>
    <candidate_id>2</candidate_id>
    <field_1>bar</field_1>
    </EF_Candidate>
    </EF_Candidate_List>

第二个XML需要基于节点合并

<EF_Candidate_List>
<EF_Candidate>
<candidate_id>1</candidate_id>
<account_number>10</account_number>
<account_number>50</account_number>
<EF_Candidate>
<candidate_id>2</candidate_id>
<account_number>20</account_number>
</EF_Candidate>
</EF_Candidate_List>

期待 xml 结果文件。

   <EF_Candidate_List>
    <EF_Candidate>
    <candidate_id>1</candidate_id>
    <field_1>foo</field_1>
    <column>10</column>
    <column>50</column>
    </EF_Candidate>
    <EF_Candidate>
    <candidate_id>2</candidate_id>
    <field_1>bar</field_1>
    <column>20</column>
    </EF_Candidate>
    </EF_Candidate_List>

我在xsl下面创建了。

    <xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:variable name="val" select="document('test2.xml')/EF_Candidate_List/EF_Candidate/account_number" />

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

<xsl:template match="EF_Candidate">
    <xsl:copy>
        <xsl:apply-templates/>
        <column>
            <xsl:value-of select="$val" />
        </column>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

它会生成下面的 xml 文件。

 <?xml version="1.0" encoding="UTF-8"?>
<EF_Candidate_List>
   <EF_Candidate>
      <candidate_id>1</candidate_id>
      <field_1>foo</field_1>
      <column>10</column>
   </EF_Candidate>
   <EF_Candidate>
      <candidate_id>2</candidate_id>
      <field_1>bar</field_1>
      <column>10</column>
   </EF_Candidate>
</EF_Candidate_List>

我对 XSLT 还很陌生,所以请原谅这个可能是新手的问题。任何指导将不胜感激。提前致谢。

【问题讨论】:

  • 好吧,尝试编写一个带有谓词的 XPath 表达式,您可以将一个文档的 EF_Candidate 中的 candidate_id 与另一个文档中的一个文档进行比较,或者使用 current() XSLT 函数或通过将一个文档中的 id 存储在一个变量中。如果有机会迁移到 XSLT 2 或 3,请使用密钥。
  • 在此处查看示例:stackoverflow.com/a/68005242/3016153

标签: xml xslt


【解决方案1】:

当您匹配 EF_Candidate 时,您可以创建一个具有当前候选人 ID 的变量。然后从 test2.xml 中获取所有帐号,其中 EF_Candidate 包含与当前候选人 ID 具有相同值的候选 ID。然后为每个帐号创建一个列元素及其值。

<xsl:stylesheet version="1.0"
            xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

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

<xsl:template match="EF_Candidate">
    <xsl:variable name="current_candidate_id" select="candidate_id"/>
    <xsl:variable name="account-numbers" select="document('test2.xml')/EF_Candidate_List/EF_Candidate[candidate_id = $current_candidate_id]/account_number" />

    <xsl:copy>
        <xsl:apply-templates/>
        <xsl:for-each select="$account-numbers">
            <column>
                <xsl:value-of select="."/>
            </column>
        </xsl:for-each>
    </xsl:copy>
</xsl:template>
</xsl:stylesheet>

【讨论】:

  • 非常感谢它按照我的要求工作。赞赏
猜你喜欢
  • 1970-01-01
  • 2013-01-19
  • 1970-01-01
  • 2015-11-04
  • 2021-03-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多