0

入力:

<persons>
    <person name="John" role="Writer"/>
    <person name="John" role="Poet"/>
    <person name="Jacob" role="Writer"/>
    <person name="Jacob" role="Poet"/>
    <person name="Joe" role="Poet"/>
</persons>

期待される出力:

<groups>
    <group roles="Wriet, Poet" persons="John, Jacob"/>
    <group roles="Poet" persons="Joe"/>
</groups>

上記の例のように、まず個人名でグループ化し、全員の役割を見つける必要があります。複数の人が同じ役割のセットを持っていることがわかった場合 (たとえば、ジョンとジェイコブの両方が作家であり詩人でもある場合)、役割のセットごとにグループ化し、人の名前をリストする必要があります。

Muenchian メソッドや EXSLTset:distinctなどを使用して、グループ化の最初のレベルでこれを行うことができます。

<groups>
    <group roles="Wriet, Poet" persons="John"/>
    <group roles="Wriet, Poet" persons="Jacob"/>
    <group roles="Poet" persons="Joe"/>
</groups>

上記は、XSLT 1.0 と EXSLT を使用して変換されました。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:sets="http://exslt.org/sets" extension-element-prefixes="sets">
    <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
    <xsl:key name="persons-by-name" match="person" use="@name"/>
    <xsl:template match="persons">
        <groups>
            <xsl:for-each select="sets:distinct(person/@name)">
                <group>
                    <xsl:attribute name="persons"><xsl:value-of select="."/></xsl:attribute>
                    <xsl:attribute name="roles">
                        <xsl:for-each select="key('persons-by-name', .)">
                            <xsl:value-of select="@role"/>
                            <xsl:if test="position()!=last()"><xsl:text>, </xsl:text></xsl:if>
                        </xsl:for-each>
                    </xsl:attribute>
                </group>
            </xsl:for-each>
        </groups>
    </xsl:template>
</xsl:stylesheet>

ただし、グループ化された役割をグループ化する方法を理解するには助けが必要です。

XSLT 1.0 ソリューションが利用できない場合は、遠慮なく XSLT 2.0 アプローチを推奨してください。

4

2 に答える 2

1

私はあなたがすでに行ったのとまったく同じことを行い、さらに一歩進んで再びグループ化しました. 今、私はあなたの入力で次の出力を取得します:

<?xml version="1.0" encoding="UTF-8"?>
<groups>
    <group roles="Writer,Poet" persons="John,Jacob"/>
    <group roles="Poet" persons="Joe"/>
</groups>

これは XSLT 2.0 です。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns="" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:avintis="http://www.avintis.com/esb" exclude-result-prefixes="#all" version="2.0">
    <xsl:output method="xml" encoding="UTF-8" indent="yes"/>

    <xsl:template match="/persons">
        <groups>
            <xsl:variable name="persons" select="."/>

            <!-- create a temporary variable containing all roles of a person -->
            <xsl:variable name="roles">
                <xsl:for-each select="distinct-values(person/@name)">
                    <xsl:sort select="."/>
                    <xsl:variable name="name" select="."/>
                    <xsl:element name="group">
                        <xsl:attribute name="roles">
                            <!-- sort the roles of each person -->
                            <xsl:variable name="rolesSorted">
                                <xsl:for-each select="$persons/person[@name=$name]">
                                    <xsl:sort select="@role"/>
                                    <xsl:copy-of select="."/>
                                </xsl:for-each>
                            </xsl:variable>
                            <xsl:value-of select="string-join($rolesSorted/person/@role,',')"/>
                        </xsl:attribute>
                        <xsl:attribute name="persons" select="."/>
                    </xsl:element>
                </xsl:for-each>
            </xsl:variable>

            <!-- now loop again over all roles of the persons and group persons having the same roles -->
            <xsl:for-each select="distinct-values($roles/group/@roles)">
                <xsl:element name="group">
                    <xsl:variable name="name" select="."/>
                    <xsl:attribute name="roles" select="$name"/>
                    <xsl:attribute name="persons">
                        <xsl:value-of select="string-join($roles/group[@roles=$name]/@persons,',')"/>
                    </xsl:attribute>
                </xsl:element>
            </xsl:for-each>
        </groups>
    </xsl:template>

    <xsl:template match="*|text()|@*">
        <xsl:copy>
            <xsl:apply-templates select="*|text()|@*"/>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

役割もソートされるため、役割や人物の入力順序とは無関係です。

于 2014-12-04T14:26:18.290 に答える