问题
I have the following XML:
<root>
<attributes>
<attribute_value>ID1</attribute_value>
<attribute_name>id</attribute_name>
</attributes>
<attributes>
<attribute_value>ID2</attribute_value>
<attribute_name>id</attribute_name>
</attributes>
<attributes>
<attribute_value>some-link</attribute_value>
<attribute_name>link</attribute_name>
</attributes>
</root>
I want to iterate over the file and concatenate all the "attribute_value" values based on the "attribute_name" value using XSLT (1.0 or 2.0). So in this case the output would be:
<root>
<element name="id" value="ID1"/>
<element name="ids" value="ID1,ID2"/>
<element name="link" value="some-link"/>
</root>
The "id" element should contain the first value encountered and the "ids" element would contain the concatenated value. How can this be achieved? I have a working XSLT where I use the tag and iterate over all the attributes, but not able to get around this problem.
The following is my current XSLT:
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" indent="yes"/>
<xsl:template match="root">
<root>
<xsl:for-each select="attributes">
<xsl:variable name="attribute_name" select="attribute_name"/>
<xsl:variable name="attribute_value" select="attribute_value"/>
<xsl:if test="$attribute_name = 'link'">
<element name="link">
<xsl:attribute name="value"><xsl:value-of select="$attribute_value" /></xsl:attribute>
</element>
</xsl:if>
</xsl:for-each>
</root>
</xsl:template>
</xsl:stylesheet>
回答1:
As you are using XSLT 2.0, you can use xsl:for-each-group
here
<xsl:for-each-group select="attributes" group-by="attribute_name">
Then to output the first element, you can do this:
<element name="{attribute_name}" value="{attribute_value}" />
(Note the use of attribute value templates to simplify creating the attributes)
Then if there are more than one element in the group, you could create the concatenated version like so:
<element name="{@attribute_name}s" value="{string-join(current-group()/attribute_value, ',')}" />
Try this XSLT
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" indent="yes"/>
<xsl:template match="root">
<root>
<xsl:for-each-group select="attributes" group-by="attribute_name">
<element name="{attribute_name}" value="{attribute_value}" />
<xsl:if test="current-group()[2]">
<element name="{@attribute_name}s" value="{string-join(current-group()/attribute_value, ',')}" />
</xsl:if>
</xsl:for-each-group>
</root>
</xsl:template>
</xsl:stylesheet>
来源:https://stackoverflow.com/questions/32502030/concatenate-xslt-element-values-based-on-another-element-value