contra8
contra8

Reputation: 27

XSLT: How to fix an xsl:sort that does not copy attribute values

I have an XML file where I want to sort the div-elements in an alphabetical order. Also inside the div-elements, I need to sort the ab-elements in an alphabetical order, too. The XSLT code basically works. But in the end, the attributes n="..." inside the div-elements are lost.

This is the XML:

<?xml version="1.0" encoding="UTF-8"?>
<TEI xmlns="http://www.tei-c.org/ns/1.0" xmlns:telota="http://www.telota.de" xmlns:hkg="http://www.gotthelf.unibe.ch" telota:doctype="ortsregister">
<text>
    <body>
        <div n="B">
            <ab xml:id="o0bcb42e7-b931-47a2-95e8-6c5ff6c5149d">
                <seg type="placeName">
                    <settlement>Berlin</settlement>
                </seg>
            </ab>
            <ab xml:id="o_glr_1xp_j3b">
                <seg type="placeName">
                    <settlement>Bonn</settlement>
                </seg>
            </ab>
            <ab xml:id="ob22d4b9b-4c4a-43fb-86fe-75f76938eb74">
                <seg type="placeName">
                    <settlement>Bern</settlement>
                </seg>
            </ab>
        </div>
        <div n="A">
            <ab xml:id="o70758a9e-41fc-40e9-a859-bdbdffe8a085">
                <seg type="placeName">
                    <settlement>Aarhus</settlement>
                    <region>Dänemark</region>
                </seg>
            </ab>
            <ab xml:id="o_x5p_4wp_j3b">
                <seg type="placeName">
                    <settlement>Aareschlaufe</settlement>
                </seg>
            </ab>
        </div>
    </body>
</text>
</TEI>

This is my XSLT:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"
xmlns:tei="http://www.tei-c.org/ns/1.0" xmlns:hkg="http://www.gotthelf.unibe.ch">
<xsl:output method="xml" indent="yes" />

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

<xsl:template match="tei:body">
    <xsl:copy>
        <xsl:apply-templates select="tei:div">
            <xsl:sort select="@n" />
        </xsl:apply-templates>
    </xsl:copy>
</xsl:template>

<xsl:template match="tei:div">
    <xsl:copy>
        <xsl:apply-templates select="tei:ab">
            <xsl:sort select="tei:seg/tei:settlement" />
        </xsl:apply-templates>
    </xsl:copy>
</xsl:template>

And this is the XML I receive after running the XSLT:

<?xml version="1.0" encoding="UTF-8"?>
<TEI xmlns="http://www.tei-c.org/ns/1.0" xmlns:telota="http://www.telota.de" xmlns:hkg="http://www.gotthelf.unibe.ch" telota:doctype="ortsregister">
<text>
    <body>
        <div>
            <ab xml:id="o_x5p_4wp_j3b">
                <seg type="placeName">
                    <settlement>Aareschlaufe</settlement>
                </seg>
            </ab>
            <ab xml:id="o70758a9e-41fc-40e9-a859-bdbdffe8a085">
                <seg type="placeName">
                    <settlement>Aarhus</settlement>
                    <region>Dänemark</region>
                </seg>
            </ab>
        </div>
        <div>
            <ab xml:id="o0bcb42e7-b931-47a2-95e8-6c5ff6c5149d">
                <seg type="placeName">
                    <settlement>Berlin</settlement>
                </seg>
            </ab>
            <ab xml:id="ob22d4b9b-4c4a-43fb-86fe-75f76938eb74">
                <seg type="placeName">
                    <settlement>Bern</settlement>
                </seg>
            </ab>
            <ab xml:id="o_glr_1xp_j3b">
                <seg type="placeName">
                    <settlement>Bonn</settlement>
                </seg>
            </ab>
        </div>
    </body>
</text>
</TEI>

So the div-elements do not have any attributes n="..." anymore. This is what I intend to have:

<?xml version="1.0" encoding="UTF-8"?>
<TEI xmlns="http://www.tei-c.org/ns/1.0" xmlns:telota="http://www.telota.de" xmlns:hkg="http://www.gotthelf.unibe.ch" telota:doctype="ortsregister">
<text>
    <body>
        <div n="A">
            <ab xml:id="o_x5p_4wp_j3b">
                <seg type="placeName">
                    <settlement>Aareschlaufe</settlement>
                </seg>
            </ab>
            <ab xml:id="o70758a9e-41fc-40e9-a859-bdbdffe8a085">
                <seg type="placeName">
                    <settlement>Aarhus</settlement>
                    <region>Dänemark</region>
                </seg>
            </ab>
        </div>
        <div n="B">
            <ab xml:id="o0bcb42e7-b931-47a2-95e8-6c5ff6c5149d">
                <seg type="placeName">
                    <settlement>Berlin</settlement>
                </seg>
            </ab>
            <ab xml:id="ob22d4b9b-4c4a-43fb-86fe-75f76938eb74">
                <seg type="placeName">
                    <settlement>Bern</settlement>
                </seg>
            </ab>
            <ab xml:id="o_glr_1xp_j3b">
                <seg type="placeName">
                    <settlement>Bonn</settlement>
                </seg>
            </ab>
        </div>
    </body>
</text>
</TEI>

I read a lot about that copy does only copy the node but not its attributes. But I still do not get what I have to do to improve my code. So any helpful hint is appreciated.

If I gave too much code I am sorry. If you need to know more please let me know. Thanks in advance.

Upvotes: 1

Views: 61

Answers (1)

Tim C
Tim C

Reputation: 70618

Copying the attributes can be done by the identity template, but for that to work you first have to select the attributes you wish to copy.

So, in your case, change the template matching tei:div to this...

<xsl:template match="tei:div">
    <xsl:copy>
        <xsl:apply-templates select="@*|tei:ab">
            <xsl:sort select="tei:seg/tei:settlement" />
        </xsl:apply-templates>
    </xsl:copy>
</xsl:template>

The <xsl:apply-templates select="@*|tei:ab"> is the relevant line here, so it selects attributes as well as the tei:ab element.

Upvotes: 1

Related Questions