是否可以对节点进行分组并使用指定的键进行合并?我的一些xml文件在两个子节点中有关于一个人的信息,我想找出节点是否是关于同一个人的,然后将其marge到一个节点中
输入xml如下所示:
<db>
<next>
<name>John</name>
<surname>Smith</surname>
<number>304888</number>
<details>
<city>Westfield</city>
<zip-code>07090</zip-code>
<address>23 Victoria Street</address>
<phone>123456789</phone>
<fax/>
</details>
</next>
<next>
<name>John</name>
<surname>Smith</surname>
<number>304888</number>
<details>
<city>Westfield</city>
<zip-code>07090</zip-code>
<address>23 Victoria Street</address>
<phone>223344123</phone>
<fax>993456789</fax>
</details>
</next>
<next>
<name>John</name>
<surname>Smith</surname>
<number>113190</number>
<details>
<city>Richmond</city>
<zip-code>3121</zip-code>
<address>18 Seasame Street</address>
<phone>123456222</phone>
<fax/>
</details>
</next>
<next>
<name>John</name>
<surname>Smith</surname>
<number>113190</number>
<details>
<city>Richmond</city>
<zip-code>3133</zip-code>
<address>23 Baker Street</address>
<phone>113344123</phone>
<fax>133456789</fax>
</details>
</next>
</db>
"number"是个人的ID,可以有更多的人具有相同的名称和安全名称,但具有不同的"number"值。此外,同一个人可能不止一次(具有相同的"name"、"surename"one_answers"number"值(,但具有不同的详细信息。如果"城市"、"邮政编码"one_answers"地址"的组合相同,但"电话"或/和"传真"不同,那么我想保留它。我希望它看起来像这样:
<db>
<next>
<name>John</name>
<surname>Smith</surname>
<number>304888</number>
<details>
<city>Westfield</city>
<zip-code>07090</zip-code>
<address>23 Victoria Street</address>
<phone>123456789</phone>
<phone>223344123</phone>
<fax>993456789</fax>
</details>
</next>
<next>
<name>John</name>
<surname>Smith</surname>
<number>113190</number>
<details>
<city>Richmond</city>
<zip-code>3121</zip-code>
<address>18 Seasame Street</address>
<phone>123456222</phone>
<fax/>
</details>
</next>
<next>
<name>John</name>
<surname>Smith</surname>
<number>113190</number>
<details>
<city>Richmond</city>
<zip-code>3133</zip-code>
<address>23 Baker Street</address>
<phone>113344123</phone>
<fax>133456789</fax>
</details>
</next>
</db>
我尝试过muenchian分组,但我不知道如何使用电话和传真节点。
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" />
<xsl:key name="index" match="next" use="number" />
<xsl:key name="details-key" match="details" use="city,'_',zip-code,'_',address" />
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="db">
<xsl:copy>
<xsl:for-each select="//next[generate-id() = generate-id(key('index', number)[1])]">
<xsl:element name="name">
<xsl:value-of select="name"/>
</xsl:element>
<xsl:element name="surname">
<xsl:value-of select="surname"/>
</xsl:element>
<xsl:element name="number">
<xsl:value-of select="number"/>
</xsl:element>
<next>
<xsl:for-each select="//details[generate-id() = generate-id(key('details-key', concat(city,'_',zip-code,'_',address))[1])]">
<xsl:element name="city">
<xsl:value-of select="city"/>
</xsl:element>
<xsl:element name="zip-code">
<xsl:value-of select="zip-code"/>
</xsl:element>
<xsl:element name="address">
<xsl:value-of select="address"/>
</xsl:element>
</xsl:for-each>
</next>
</xsl:for-each>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
首先,样式表将产生错误,因为您在中使用的表达式
<xsl:key name="details-key" match="details" use="city,'_',zip-code,'_',address" />
不是XPath 1.0中的有效表达式。
如果您想通过city
、zip-code
和address
的组合值对details
元素进行分组,您应该将密钥定义为:
<xsl:key name="details-key" match="details" use="concat(city, '_', zip-code, '_', address)" />
现在,如果我按您的预期输出而不是按您的描述,您实际上希望为number
和地址的每个唯一组合创建一个组。因此,大致如下:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" />
<xsl:key name="k1" match="next" use="concat(number, '_', details/city,'_', details/zip-code,'_', details/address)" />
<xsl:template match="db">
<xsl:copy>
<xsl:for-each select="next[generate-id() = generate-id(key('k1', concat(number, '_', details/city,'_', details/zip-code,'_', details/address))[1])]">
<next>
<xsl:copy-of select="name | surname | number"/>
<details>
<xsl:copy-of select="city | zip-code | address"/>
<xsl:variable name="group-details" select="key('k1', concat(number, '_', details/city,'_', details/zip-code,'_', details/address))/details" />
<xsl:copy-of select="$group-details/phone[text()] | $group-details/fax[text()]"/>
</details>
</next>
</xsl:for-each>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>