XSLT: Sorting authors based on surnames and based

2019-08-31 17:49发布

问题:

My code is unable to sort the names, when 'use-character-maps' module is used. Without CharMap, I am able to get the required result.

Sorting should be based on CharMap character also, i.e., 'Anupam' should be the third author in result (my code is listing him at the end). Please suggest. (XSLT2 vesrion)

XML:

<article>
 <aug>
    <author><surname>Akhil</surname><fnm>GH</fnm></author>
    <author><surname>Kishan</surname><fnm>TR</fnm></author>
    <author><surname>&#x000C1;nupam</surname><fnm>TP</fnm></author>
    <author><surname>Abhi</surname><fnm>TD</fnm></author>
 </aug>
</article>

XSLT:

 <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text" use-character-maps="chars"/>
    <xsl:character-map name="chars">
        <xsl:output-character character="&#x000C1;" string="A"/>
    </xsl:character-map>
    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="aug">
        <aug>
        <xsl:for-each select="author">
            <xsl:sort select="surname"/>
            <au><xsl:apply-templates select="surname"/><xsl:text> </xsl:text><xsl:apply-templates select="fnm"/></au>
        </xsl:for-each>
        </aug>
    </xsl:template>
</xsl:stylesheet>

Required Result:

<article>
 <aug>
    <author><surname>Abhi</surname><fnm>TD</fnm></author>
    <author><surname>Akhil</surname><fnm>GH</fnm></author>
    <author><surname>Anupam</surname><fnm>TP</fnm></author>
    <author><surname>Kishan</surname><fnm>TR</fnm></author>
 </aug>
</article>

回答1:

Character maps are a serialization feature and serialization only happens as a final step after a result tree has been created. So you would need to run two separate transformations, one that applies your character map (for instance with an identity transformation) and creates a result file, a second that consumes the result file and does the sorting.

As an alternative, and depending on the XSLT processor you use, for instance with Saxon 9, you might want to check whether using a collation solves the problem of the sorting:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes" use-character-maps="chars"/>
    <xsl:character-map name="chars">
        <xsl:output-character character="&#x000C1;" string="A"/>
    </xsl:character-map>
    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="aug">
        <aug>
        <xsl:for-each select="author">
            <xsl:sort select="surname" collation="http://saxon.sf.net/collation?lang=en&amp;ignore-modifiers=yes"/>
            <au><xsl:apply-templates select="surname"/><xsl:text> </xsl:text><xsl:apply-templates select="fnm"/></au>
        </xsl:for-each>
        </aug>
    </xsl:template>
</xsl:stylesheet>

See http://saxonica.com/documentation/index.html#!extensibility/collation for details.



标签: xslt