需要使用基于不同属性和分组依据的 XSLT2.0 基于另一个 XML 创建 XML

Need to create XML based on another XML using XSLT2.0 based on distinct attributes and group by

我正在尝试根据另外 2 个 XML 生成一个 XML。我正在轮询一个 returns 人详细信息的数据库(查询中可以返回 n 人)。 最后的 XML 应该有 数据标签 的确切数量作为 XML 来自 DB。例如:

1st XML- 从 DB

获取
<parent>
    <child>
        <name>John</name>
        <city>Boston</city>
    </child>
    <child>
        <name>John</name>
        <city>Seattle</city>
    </child>
    <child>
        <name>Allison</name>
        <city>Houston</city>
    </child>
    <child>
        <name>John</name>
        <city>Boston</city>
    </child>
</parent>

第 2 个 XML- 从其他来源获取此信息

<details>
    <detail>
        <city>Boston</city>
        <code>abc</code>
    </detail>
    <detail>
        <city>Houston</city>
        <code>xyz</code>
    </detail>
</details>

首先,我需要创建 2 个数据标签,因为有 2 个不同的名称(John 和 Allison),然后我需要一个一个地检查所有 City 标签 child 第一个 XML 中的标签与第二个 XML 中的 匹配,然后创建 Details 标记并复制 Code 标记及其在 Final XML.

中的值

1) 如果没有匹配的条目,则不应创建详细信息标签,因为没有匹配的条目。 2)不,永远不会有多个匹配条目。应根据匹配城市标签的数量,根据 Distinct NAME 标签和详细信息标签创建数据标签。

待生成最终 XML

<FinalData>
    <Data>
        <name>John</name>
        <details>
            <city>Boston</city>
            <code>xyz</code>
        </details>
    </Data>
    <Data>
        <name>Allison</name>
        <details>
            <city>Houston</city>
            <code>abc</code>
        </details>
    </Data>
</FinalData>

编辑 1:

我在填充 code 标签 时遇到问题,因为我必须在 XML 中匹配 city 标签 s 并且需要一个 for 循环来匹配。

下面是我的尝试 -

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    <xsl:param name="otherFile" select="document('SOF Input 2.xml')"/>
    <xsl:template match="parent">
        <FinalData>
            <xsl:for-each-group select="child" group-by="name">
                <data>
                    <name>
                        <xsl:value-of select="name"/>
                    </name>
                    <details>
                        <city>
                            <xsl:value-of select="city"/>
                        </city>
                        <code>
                            <xsl:for-each select="$otherFile/details/detail">
                                <xsl:if test="parent/child/city='/city'">
                                    <!--I am getting stuck here - not able to get value here..i guess both city tags are referring to the same-->
                                    <xsl:value-of select="/code"/>
                                </xsl:if>
                            </xsl:for-each>
                        </code>
                    </details>
                </data>
                <xsl:text>
</xsl:text>
            </xsl:for-each-group>
        </FinalData>
    </xsl:template>
</xsl:stylesheet>

我得到以下输出 -

<?xml version="1.0" encoding="UTF-8"?>
<FinalData><data>
        <name>John</name>
        <details>
            <city>Boston</city>
            <code/>
        </details>
    </data>
<data>
        <name>Allison</name>
        <details>
            <city>Houston</city>
            <code/>
        </details>
    </data>
</FinalData>

它的缩进也有点错误。如果我遗漏了什么,请告诉我。

编辑 2:

Michael所说的场景恐怕比预想的要早得多。 city 标签将重复但位于 parent 标签下。 city 标签的值在 parent 标签中是唯一的。我必须从所有匹配的 city 标签中逐个获取所有父级的值,并以 parent 中匹配的方式填充标签进入输出 XML 中相应的 详细信息 标签。 PFB 示例 XMLs,这将以更好的方式解释 -

第一 XML -

<parent>
    <child>
        <name>John</name>
        <city>Boston</city>
    </child>
    <child>
        <name>John</name>
        <city>Seattle</city>
    </child>
    <child>
        <name>Allison</name>
        <city>Houston</city>
    </child>
    <child>
        <name>John</name>
        <city>Boston</city>
    </child>
</parent>

第二XML-

<details>
    <parent>
        <detail>
            <city>Boston</city>
            <code>abc</code>
        </detail>
        <detail>
            <city>Houston</city>
            <code>xyz</code>
        </detail>
    </parent>
    <parent>
        <detail>
            <city>Boston</city>
            <code>abc</code>
        </detail>
        <detail>
            <city>Seattle</city>
            <code>mno</code>
        </detail>
    </parent>
    <parent>
        <detail>
            <city>Houston</city>
            <code>xyz</code>
        </detail>
        <detail>
            <city>Seattle</city>
            <code>mno</code>
        </detail>
    </parent>
</details>

最终预期 XML-

<FinalData>
    <Data>
        <name>John</name>
        <details>
            <detail>
                <city value="Boston">abc</city>
            </detail>
            <detail>
                <city value="Boston">abc</city>
                <city value="Seattle">mno</city>
            </detail>
            <detail>
                <city value="Seattle">mno</city>
            </detail>
        </details>
    </Data>
    <Data>
        <name>Allison</name>
        <details>
            <detail>
                <city value="Houston">xyz</city>
            </detail>
            <detail>
                <city value="Houston">xyz</city>
            </detail>
        </details>
    </Data>
</FinalData>

希望这是清楚的,因为我不擅长解释。

声明一个密钥

<xsl:key name="city" match="detail" use="city"/>

然后使用

<xsl:copy-of select="key('city', city, $otherFile)/code"/>

在您的 for-each-group 中输出匹配代码。

这样试试?

XSLT 2.0

<xsl:stylesheet version="2.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="otherFile" select="document('SOF Input 2.xml')"/>

<xsl:key name="detail-by-city" match="detail" use="city" />

<xsl:template match="/parent">
    <FinalData>
        <xsl:for-each-group select="child" group-by="name">
            <data>
                <xsl:copy-of select="name"/>
                <xsl:for-each select="key('detail-by-city', current-group()/city, $otherfile)">
                    <details>
                         <xsl:copy-of select="*"/>
                    </details>
                </xsl:for-each>
            </data>
        </xsl:for-each-group>
    </FinalData>
</xsl:template>

</xsl:stylesheet>

这是假设一个组在另一个文档中可以有多个匹配条目,并且您想为每个条目创建一个单独的 details 节点。