Concatenate XSLT element values based on another element value

烈酒焚心 提交于 2019-12-12 00:53:53

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!