比较 2 组子节点以查找至少一个子节点值与其他子节点值之一匹配的匹配项



我有这个XML,其中包含两组表数据(为简单起见,元素名称已通用化)。

<root>
    <table>
        <Row type="1">
            <Id>AAAA</Id>
            <Properties>
                <Property>A</Property>
                <Property>D</Property>
            </Properties>
        </Row>
        <Row type="1">
            <Id>BBBB</Id>
            <Properties>
                <Property>B</Property>
            </Properties>
        </Row>
        <Row type="1">
            <Id>CCCC</Id>
            <Properties>
                <Property>G</Property>
                <Property>H</Property>
            </Properties>
        </Row>
    </table>
    <table>
        <Row type="2">
            <Id>123abc</Id>
            <Properties>
                <Property>A</Property>
                <Property>D</Property>
                <Property>E</Property>
            </Properties>
        </Row>
        <Row type="2">
            <Id>456def</Id>
            <Properties>
                <Property>B</Property>
                <Property>C</Property>
                <Property>I</Property>
            </Properties>
        </Row>
        <Row type="2">
            <Id>798ghi</Id>
            <Properties>
                <Property>F</Property>
                <Property>G</Property>
                <Property>H</Property>
            </Properties>
        </Row>
    </table>
</root>

我正在尝试编写一个转换来输出一个新表,该表根据表1的属性将表1中的行与表2中的行相关联。 表 1 中的行不需要在表 2 中的行中存在所有属性;任何一个属性都是被视为匹配项所需的全部内容。 表 1 中的行与表 2 中的行之间始终只有一对一的关系。

我想要的输出是:

<root>
    <Row>
        <Name>NewTable:AAAA</Name>
        <Table2Id>123abc</Table2Id>
    </Row>
    <Row>
        <Name>NewTable:BBBB</Name>
        <Table2Id>456def</Table2Id>>
    </Row>
    <Row>
        <Name>NewTable:CCCC</Name>
        <Table2Id>789ghi</Table2Id>
    </Row>
</root>

从这个开始,并一直试图遵循这个逻辑:为我找到表 2 中行的 Id 标记,该标签至少有一个属性与表 1 中正在处理的当前行的属性之一匹配。

这是我到目前为止所拥有的。 它不起作用,但我觉得我很接近。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
    <xsl:template match="//Row[@type != '2']">
            <xsl:variable name="Name" select="concat('NewTable:', ./Id)"/>
            <Row>
                <Name>
                    <xsl:value-of select="$Name"/>
                </Name>
                <Table2Id>
                    <xsl:value-of select="//Row[@type = '2'][Property = ./Property]/Id"/>
                </Table2Id>
            </Row>
    </xsl:template>
    <xsl:template match="/">
        <root>
            <xsl:apply-templates/>
        </root>
    </xsl:template>
    <xsl:template match="text()"/>
</xsl:stylesheet>    

这里有两件事非常有用:一是 XSLT 的关键功能,它允许您基于匹配值创建关系。另一种是集合比较,如果一个集合的至少一个成员与另一个集合的至少一个成员匹配,则集合将被视为匹配。

尝试以下利用两者的样式表:

<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:key name="table2" match="Row[@type=2]" use="Properties/Property" />
<xsl:template match="/">
<root>
    <xsl:for-each select="root/table/Row[@type=1]">
    <row>   
        <Name>
            <xsl:value-of select="Id" />
        </Name>
        <Table2Id>
            <xsl:value-of select="key('table2', Properties/Property)/Id" />
        </Table2Id>
    </row>
    </xsl:for-each>
</root>
</xsl:template>
</xsl:stylesheet>

顺便说一句,如果您使用以下方法,您的方法也会起作用(尽管效率较低):

[Properties/Property = ./Properties/Property]

而不仅仅是:

[Property = ./Property]

因为你在<Row><Property>的祖父母)的背景下。

相关内容

最新更新