我有这个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>
的祖父母)的背景下。