Re: [xsl] how to create an exclusion list from a variable?

Subject: Re: [xsl] how to create an exclusion list from a variable?
From: Martin Honnen <Martin.Honnen@xxxxxx>
Date: Sat, 28 Nov 2009 15:03:15 +0100
ivanmacculi@xxxxxxxxx wrote:
HI all, i've this xml and i'm tryng to change the value of the attributes. This is what i have:

<mets:div LABEL="Canto I">
                    <mets:div LABEL="Pagina 7">
                        <mets:fptr FILEID="file.00010"/>
                    </mets:div>
                    <mets:div LABEL="Pagina 8">
                        <mets:fptr FILEID="file.00011"/>
                    </mets:div>
                    <mets:div LABEL="Pagina 9">
                        <mets:fptr FILEID="file.00012"/>
                    </mets:div>
                    <mets:div LABEL="Pagina 10">
                        <mets:fptr FILEID="file.00013"/>
                    </mets:div>
                    <mets:div LABEL="Pagina 11">
                        <mets:fptr FILEID="file.00014"/>
                    </mets:div>
                    <mets:div LABEL="Pagina 12">
                        <mets:fptr FILEID="file.00015"/>
                    </mets:div>
                    <mets:div LABEL="Pagina 13">
                        <mets:fptr FILEID="file.00016"/>
                    </mets:div>
                    <mets:div LABEL="Pagina 14">
                        <mets:fptr FILEID="file.00017"/>
                    </mets:div>
                    <mets:div LABEL="Pagina 15">
                        <mets:fptr FILEID="file.00018"/>
                    </mets:div>
                    <mets:div LABEL="Pagina 16">
                        <mets:fptr FILEID="file.00019"/>
                    </mets:div>
                    <mets:div LABEL="Pagina 17">
                        <mets:fptr FILEID="file.00020"/>
                    </mets:div>
                </mets:div>

this is what i would like to obtain:

<mets:div LABEL="Canto I">
                    <mets:div LABEL="Pagina 7">
                        <mets:fptr FILEID="file.00010"/>
                    </mets:div>
                    <mets:div LABEL="Carta [1r]">
                        <mets:fptr FILEID="file.00011"/>
                    </mets:div>
                    <mets:div LABEL="Carta [1v]">
                        <mets:fptr FILEID="file.00012"/>
                    </mets:div>
                    <mets:div LABEL="Carta [2r]">
                        <mets:fptr FILEID="file.00013"/>
                    </mets:div>
                    <mets:div LABEL="Carta [2v]">
                        <mets:fptr FILEID="file.00014"/>
                    </mets:div>
                    <mets:div LABEL="Carta [3r]">
                        <mets:fptr FILEID="file.00015"/>
                    </mets:div>
                    <mets:div LABEL="Pagina 13">
                        <mets:fptr FILEID="file.00016"/>
                    </mets:div>
                    <mets:div LABEL="Carta [3v]">
                        <mets:fptr FILEID="file.00017"/>
                    </mets:div>
                    <mets:div LABEL="Carta [4r]">
                        <mets:fptr FILEID="file.00018"/>
                    </mets:div>
                    <mets:div LABEL="Carta [4v]">
                        <mets:fptr FILEID="file.00019"/>
                    </mets:div>
                    <mets:div LABEL="Carta [5r]">
                        <mets:fptr FILEID="file.00020"/>
                    </mets:div>
                </mets:div>

Here is an adaption of the earlier stylesheet: it takes a parameter, a sequence of strings, where you can list the LABEL attribute values to exclude:


<xsl:stylesheet
exclude-result-prefixes="#all" version="2.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema";
xmlns:mets="http://www.loc.gov/METS/"; xmlns:mix="http://www.loc.gov/mix/"; xmlns:xlink="http://www.w3.org/1999/xlink";
xmlns:rd="http://cosimo.stanford.edu/sdr/metsrights/"; xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>


<xsl:param name="pages-to-exclude" as="xs:string*" select="('Pagina 7', 'Pagina 13')"/>

<xsl:output indent="yes" method="xml"/>

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

<xsl:template match="mets:div/@LABEL[not(. = $pages-to-exclude) and matches(., '^Pagina [0-9]+$')]">
<xsl:variable name="n">
<xsl:number level="any" count="mets:div[@LABEL[not(. = $pages-to-exclude) and matches(.,
'^Pagina [0-9]+$')]]"/>
</xsl:variable>
<xsl:attribute name="LABEL" select="concat('Carta [', if ($n mod 2 =
0) then concat(($n + 1) idiv 2, 'v]') else concat(($n + 1) idiv 2, 'r]'))"/>
</xsl:template>


</xsl:stylesheet>



With Michael Kay's suggestion the stylesheet could be written as

<xsl:stylesheet
exclude-result-prefixes="#all" version="2.0"
xmlns:f="http://example.com/f";
xmlns:xs="http://www.w3.org/2001/XMLSchema";
xmlns:mets="http://www.loc.gov/METS/"; xmlns:mix="http://www.loc.gov/mix/"; xmlns:xlink="http://www.w3.org/1999/xlink";
xmlns:rd="http://cosimo.stanford.edu/sdr/metsrights/"; xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>


<xsl:param name="pages-to-exclude" as="xs:string*" select="('Pagina 7', 'Pagina 13')"/>

<xsl:variable name="g" as="element()*"
select="//mets:div[@LABEL[not(. = $pages-to-exclude) and matches(., '^Pagina [0-9]+$')]]"/>


<xsl:output indent="yes" method="xml"/>

<xsl:function name="f:index-of-node" as="xs:integer*">
  <xsl:param name="nodes" as="node()*"/>
  <xsl:param name="node" as="node()"/>
  <xsl:for-each select="$nodes">
    <xsl:sequence select="position()[current() is $node]"/>
  </xsl:for-each>
</xsl:function>

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

<xsl:template match="*[. intersect $g]/@LABEL">
<xsl:variable name="n" select="f:index-of-node($g, ..)"/>
<xsl:attribute name="LABEL" select="concat('Carta [', if ($n mod 2 =
0) then concat(($n + 1) idiv 2, 'v]') else concat(($n + 1) idiv 2, 'r]'))"/>
</xsl:template>


</xsl:stylesheet>
--

	Martin Honnen
	http://msmvps.com/blogs/martin_honnen/

Current Thread