在连接父元素下的所有子元素时遇到问题。
这是源数据
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<PurchaseOrder id="abc">
<attr attr-name="A">
<new-value>123</new-value>
</attr>
<attr attr-name="B">
<new-value>99</new-value>
</attr>
<attr attr-name="B">
<new-value>77</new-value>
</attr>
<attr attr-name="C">
<new-value>1</new-value>
<new-value>2</new-value>
<new-value>3</new-value>
<new-value>4</new-value>
<new-value>5</new-value>
<new-value>6</new-value>
<new-value>7</new-value>
<new-value>8</new-value>
</attr>
<attr attr-name="D">
<new-value>
<child1>567</child1>
<child2>2</child2>
</new-value>
</attr>
<attr attr-name="E">
<new-value>
<child3>890</child3>
<child4>3</child4>
</new-value>
</attr>
</PurchaseOrder>
使用XSLT转换
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ns0="urn:demo:PurchaseOrder">
<xsl:output method="xml" indent="yes" />
<xsl:strip-space elements="*" />
<xsl:key name="keyAttrName" match="attr" use="@attr-name" />
<xsl:template match="PurchaseOrder">
<ns0:PurchaseOrderMSG>>
<Orders>
<Order id="{@id}">
<xsl:for-each select="attr[generate-id() = generate-id(key('keyAttrName', @attr-name)[1])]">
<xsl:variable name="nodeName" select="@attr-name" />
<xsl:choose>
<xsl:when test="key('keyAttrName', @attr-name)/new-value/*/node()">
<xsl:for-each select="new-value">
<xsl:element name="{$nodeName}">
<xsl:copy-of select="*" />
</xsl:element>
</xsl:for-each>
</xsl:when>
<xsl:when test="key('keyAttrName', @attr-name)/new-value/materials/material">
<xsl:for-each select="key('keyAttrName', @attr-name)">
<xsl:element name="{$nodeName}">
<xsl:copy-of select="attr" />
</xsl:element>
</xsl:for-each>
</xsl:when>
<xsl:otherwise>
<xsl:for-each select="key('keyAttrName', @attr-name)">
<xsl:element name="{$nodeName}">
<xsl:if test="position()!=1">
<ns0:text>|</ns0:text>
</xsl:if>
<xsl:value-of select="."/>
</xsl:element>
</xsl:for-each>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</Order>
</Orders>
</ns0:PurchaseOrderMSG>
</xsl:template>
</xsl:stylesheet>
预期结果应为
<?xml version="1.0" encoding="UTF-8"?>
<ns0:PurchaseOrderMSG xmlns:ns0="urn:demo:PurchaseOrder">
<Orders>
<Order>
<A>123</A>
<B>99</B>
<B>77</B>
<C>1|2|3|4|5|6|7|8</C>
<D>
<child1>567</child1>
<child2>2</child2>
</D>
<E>
<child3>890</child3>
<child4>3</child4>
</E>
</Order>
</Orders>
</ns0:PurchaseOrderMSG>
我使用的XSLT附带的输出如下所示。分隔符逻辑不起作用。
<?xml version="1.0" encoding="UTF-8"?>
<ns0:PurchaseOrderMSG xmlns:ns0="urn:demo:PurchaseOrder">
<Orders>
<Order>
<A>123</A>
<B>99</B>
<B>77</B>
<C>12345678</C>
<D>
<child1>567</child1>
<child2>2</child2>
</D>
<E>
<child3>890</child3>
<child4>3</child4>
</E>
</Order>
</Orders>
</ns0:PurchaseOrderMSG>
我尝试过在一些博客中提到的逻辑,但没有运气
XSLT merging/concatenating values of siblings nodes of same name into single node
Concatenate several child items into one child item using XSLT
答案 0 :(得分:1)
您需要修改<xsl:otherwise>
条件以处理<new-value>
节点中的值,如下所示。如果<new-value>
个子节点的数量是&gt; 1,然后使用分隔符执行连接,否则只按原样输出值。
<xsl:otherwise>
<xsl:for-each select="key('keyAttrName', @attr-name)">
<xsl:element name="{$nodeName}">
<xsl:choose>
<xsl:when test="count(new-value) > 1">
<xsl:for-each select="new-value">
<xsl:value-of select="." />
<xsl:if test="position() != last()">
<xsl:value-of select="'|'" />
</xsl:if>
</xsl:for-each>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="." />
</xsl:otherwise>
</xsl:choose>
</xsl:element>
</xsl:for-each>
</xsl:otherwise>
完整的XSLT和输出如下。
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ns0="urn:demo:PurchaseOrder">
<xsl:output method="xml" indent="yes" />
<xsl:strip-space elements="*" />
<xsl:key name="keyAttrName" match="attr" use="@attr-name" />
<xsl:template match="PurchaseOrder">
<ns0:PurchaseOrderMSG>
<Orders>
<Order id="{@id}">
<xsl:for-each select="attr[generate-id() = generate-id(key('keyAttrName', @attr-name)[1])]">
<xsl:variable name="nodeName" select="@attr-name" />
<xsl:choose>
<xsl:when test="key('keyAttrName', @attr-name)/new-value/*/node()">
<xsl:for-each select="new-value">
<xsl:element name="{$nodeName}">
<xsl:copy-of select="*" />
</xsl:element>
</xsl:for-each>
</xsl:when>
<xsl:when test="key('keyAttrName', @attr-name)/new-value/materials/material">
<xsl:for-each select="key('keyAttrName', @attr-name)">
<xsl:element name="{$nodeName}">
<xsl:copy-of select="attr" />
</xsl:element>
</xsl:for-each>
</xsl:when>
<xsl:otherwise>
<xsl:for-each select="key('keyAttrName', @attr-name)">
<xsl:element name="{$nodeName}">
<xsl:choose>
<xsl:when test="count(new-value) > 1">
<xsl:for-each select="new-value">
<xsl:value-of select="." />
<xsl:if test="position() != last()">
<xsl:value-of select="'|'" />
</xsl:if>
</xsl:for-each>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="." />
</xsl:otherwise>
</xsl:choose>
</xsl:element>
</xsl:for-each>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</Order>
</Orders>
</ns0:PurchaseOrderMSG>
</xsl:template>
</xsl:stylesheet>
输出
<ns0:PurchaseOrderMSG xmlns:ns0="urn:demo:PurchaseOrder">
<Orders>
<Order id="abc">
<A>123</A>
<B>99</B>
<B>77</B>
<C>1|2|3|4|5|6|7|8</C>
<D>
<child1>567</child1>
<child2>2</child2>
</D>
<E>
<child3>890</child3>
<child4>3</child4>
</E>
</Order>
</Orders>
</ns0:PurchaseOrderMSG>