简体   繁体   English

如何创建 XSLT 以基于两个 XML 文档之间的兄弟节点文本匹配来合并两个文档?

[英]How do I create an XSLT to merge two XML documents based on a sibling node text matching between the two?

I'm asking for some assistance with the following problem.我正在就以下问题寻求一些帮助。 I'm trying to create an XSLT that will ultimately merge the contents between Main.xml & Main_2.xml.我正在尝试创建一个 XSLT,它最终将合并 Main.xml 和 Main_2.xml 之间的内容。 These are contrived examples but the structure is correct.这些都是人为的例子,但结构是正确的。 The goal is simply to replace any 'fff' and 'zzz' elements from Main.xml with 'ggg' elements and its children from Main_2.xml if their 'ccc' siblings match in both Main.xml and Main_2.xml. The goal is simply to replace any 'fff' and 'zzz' elements from Main.xml with 'ggg' elements and its children from Main_2.xml if their 'ccc' siblings match in both Main.xml and Main_2.xml. The rest of Main.xml must be left unchanged. Main.xml 的 rest 必须保持不变。 Any pointers or references are appreciated.任何指针或引用表示赞赏。

Main.xml主要.xml

<aaa>
    <bbb>
        <ccc>1234</ccc>
        <ddd>apple</ddd>
        <eeee>oranges</eeee>
        <fff>bananas</fff>
    </bbb>
    <bbb>
        <ccc>9876</ccc>
        <ddd>pears</ddd>
        <eeee>watermelon</eeee>
        <zzz>grapes</zzz>
    </bbb>
</aaa>

Main_2.xml Main_2.xml

<aaa>
    <bbb>
        <ccc>1234</ccc>
        <ddd>apple</ddd>
        <eeee>oranges</eeee>
        <ggg>
            <hhh>asdf</hhh>
            <iii>
                <jjj>blue</jjj>
                <kkk>red</kkk>
                <lll>green</lll>
            </iii>
        </ggg>
    </bbb>
    <bbb>
        <ccc>9876</ccc>
        <ddd>pears</ddd>
        <eeee>watermelon</eeee>
        <ggg>
            <hhh>fdsa</hhh>
            <iii>
                <jjj>purple</jjj>
                <kkk>yellow</kkk>
                <lll>white</lll>
            </iii>
        </ggg>
    </bbb>
    <bbb>
        <ccc>45678</ccc>
        <ddd>veggies</ddd>
        <eeee>carrots</eeee>
        <ggg>
            <hhh>zxcf</hhh>
            <iii>
                <jjj>cyan</jjj>
                <kkk>black</kkk>
            </iii>
        </ggg>
    </bbb>
</aaa>

Desired output所需 output

<aaa>
    <bbb>
        <ccc>1234</ccc>
        <ddd>apple</ddd>
        <eeee>oranges</eeee>
        <ggg>
            <hhh>asdf</hhh>
            <iii>
                <jjj>blue</jjj>
                <kkk>red</kkk>
                <lll>green</lll>
            </iii>
        </ggg>
    </bbb>
    <bbb>
        <ccc>9876</ccc>
        <ddd>pears</ddd>
        <eeee>watermelon</eeee>
        <ggg>
            <hhh>fdsa</hhh>
            <iii>
                <jjj>purple</jjj>
                <kkk>yellow</kkk>
                <lll>white</lll>
            </iii>
        </ggg>
    </bbb>
</aaa>

Current XSLT当前 XSLT

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

    <xsl:output method="xml" indent="yes" version="1.0" encoding="utf-8" />

    <xsl:variable name="tempMain" select="document('Main_2.xml')"/>

<!-- attempt at using key, didn't pan out
    <xsl:key name="fruits" match="bbb" use="ccc"/>
-->

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


    <!-- Replace these fields with new ones -->
    <xsl:template match="fff | zzz">
        <xsl:copy-of select="$tempMain/aaa/bbb[ccc = current()../ccc]/ggg"/>

    </xsl:template>  -->

</xsl:stylesheet>

As a side question that's not entirely related, what resources would you recommend when creating XSLTs?作为一个不完全相关的附带问题,在创建 XSLT 时您会推荐哪些资源? I've gone through the tutorial on w3schools, which isn't the greatest.我已经完成了关于 w3schools 的教程,这不是最好的。 I feel like I'm just copying bits and pieces from different questions and seeing what works but would rather improve my knowledge.我觉得我只是从不同的问题中复制点点滴滴,看看什么有效,但宁愿提高我的知识。

Edit The answer by michael.hor257k works, I just need to modify it so that it doesn't remove fff or zzz elements if ccc text isn't found in Main_2.xml编辑michael.hor257k 的答案有效,我只需要修改它,如果在 Main_2.xml 中找不到 ccc 文本,它就不会删除 fff 或 zzz 元素

Try it this way?试试这个方法?

XSLT 1.0 XSLT 1.0

<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:param name="path-to-lookup"> Main_2.xml</xsl:param>
<xsl:key name="fruits" match="bbb" use="ccc"/>

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

<xsl:template match="fff | zzz">
    <xsl:variable name="key" select="../ccc"/>
    <!-- switch context to use key -->
    <xsl:for-each select="document($path-to-lookup)">
        <xsl:apply-templates select="key('fruits', $key)/ggg"/>
    </xsl:for-each>
</xsl:template>

</xsl:stylesheet>

Added:添加:

how could I modify it to not delete fff or zzz elements if the text from ccc in Main.xml doesn't match a ccc element from Main_2.xml?如果 Main.xml 中的 ccc 文本与 Main_2.xml 中的 ccc 元素不匹配,我该如何修改它以不删除 fff 或 zzz 元素?

In such case I might give up on the use of key, and do:在这种情况下,我可能会放弃使用密钥,并执行以下操作:

<xsl:template match="fff | zzz">
    <xsl:variable name="lookup" select="document($path-to-lookup)/aaa/bbb[ccc=current()/../ccc]"/>
    <xsl:choose>
        <xsl:when test="$lookup">
            <xsl:copy-of select="$lookup/ggg"/>
        </xsl:when>
        <xsl:otherwise>
            <xsl:copy-of select="."/>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM