oleksii.sapov-erlinger
oleksii.sapov-erlinger

Reputation: 412

template with specified mode does not match problem

I need to calculate a few values and store them in a variable. I pass a document node into xsl:apply-templates and specify the mode:

<xsl:variable as="xs:string*" name="checkAccidentalsVisibility">        
    <xsl:apply-templates  mode="checkAccidentalsVisibility" select="$extractMainVersion"/>  
</xsl:variable>

But the template for this mode does not match:

<xsl:template match="body//@accid[not(parent::accid/@func[. = 'caution'] or ancestor::note[@grace])]" mode="checkAccidentalsVisibility" >...

The identity transform template is specified like this, bcs I don't need to copy the xml tree.

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

The value of $checkAccidentalsVisibility is the text node. For instance, applied on this XML I get an example:

<?xml version="1.0" encoding="UTF-8"?>
    <mei meiversion="3.0.0" xml:id="dme92517025-f4c2-4231-a1c3-b70f02802d61" xmlns="http://www.music-encoding.org/ns/mei">
        <meiHead meiversion="3.0.0">
            <fileDesc>
                <titleStmt>
                    <title label="NMA digital" type="unit">an example</title>
                </titleStmt>
                <pubStmt/>
            </fileDesc>
        </meiHead>
        <music meiversion="3.0.0">
            <body>
                <mdiv n="2a" xml:id="mdiv_">
                    <score xml:id="score_">                     
                        <section label="menuetto_A" xml:id="section_A_m1-5">
                            <measure n="1" xml:id="m1_k_">
                                <staff n="1" xml:id="staff_108">
                                    <layer n="1" xml:id="layer_114">
                                        <note accid.ges="f" dur="2" oct="4" pname="e" tstamp="1" xml:id="note_120"/>
                                        <choice xml:id="choice_132">
                                            <sic xml:id="corr_132">
                                                <note dur="4" oct="4" pname="e" tstamp="3" xml:id="note_132">
                                                    <accid accid="f"  xml:id="accid_138"/>
                                                </note>
                                            </sic>
                                            <orig xml:id="orig_132">
                                                <note dur="4" oct="4" pname="e" tstamp="3" xml:id="note_132b">
                                                    <accid accid="f"  xml:id="accid_138b"/>
                                                </note>
                                            </orig>
                                        </choice>
                                    </layer>
                                </staff>
                            </measure>
                        </section>
                    </score>
                </mdiv>
            </body>
        </music>
    </mei>

I am expecting a sequence of @xml:id-values which I derive from my calculations.

Upvotes: 0

Views: 288

Answers (4)

Benjamin W. Bohl
Benjamin W. Bohl

Reputation: 340

As Michael Kay pointed out it's the missing override for the default attribute template, the latter being something like:

<xsl:template match="@*">
  <xsl:value-of select="."/>
</xsl:template>

So you should add something similar to:

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

Upvotes: 1

oleksii.sapov-erlinger
oleksii.sapov-erlinger

Reputation: 412

The whole xslt is quite large and modularized. I do not know how is it possible to post here all the content... E.g. this is the main stylesheet:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet exclude-result-prefixes="xs xd mei dme map" version="3.0" xmlns:dme="http://www.mozarteum.at/ns/dme" xmlns:map="http://www.w3.org/2005/xpath-functions/map" xmlns:mei="http://www.music-encoding.org/ns/mei" xmlns:xd="http://www.oxygenxml.com/ns/doc/xsl" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xpath-default-namespace="http://www.music-encoding.org/ns/mei">


    <xsl:include href="modules/basic.xsl"/>
    <xsl:include href="modules/extractMainVersion.xsl"/>
    <xsl:include href="modules/check_contextNote.xsl"/>
    <xsl:include href="modules/changeAccid.xsl"/>


    <xsl:variable as="xs:string*" name="checkAccidentalsVisibility">
        <xsl:variable name="extractMainVersion">
            <xsl:apply-templates mode="extractMainVersion" select="."/>
        </xsl:variable>
        <xsl:apply-templates  mode="checkAccidentalsVisibility" select="$extractMainVersion//@accid"/>
    </xsl:variable>

    <xd:doc>
        <xd:desc/>
    </xd:doc>
    <xsl:template match="/">
        <xsl:apply-templates mode="changeAccid" select="."/>
    </xsl:template>

</xsl:stylesheet>

The template

<xsl:template match="body//@accid[not(parent::accid/@func[. = 'caution'] or ancestor::note[@grace])]" mode="checkAccidentalsVisibility" >...

is placed in check_contextNote.xsl. And this is the only template with the mode checkAccidentalsVisibility but it calls plenty of other templates and functions later.

Originally, I didn't have the $checkAccidentalsVisibility and did not need to have various modes and the template was matched well. Later, I needed to change the program logic and separate the following:

  1. Change the original document-node() based on the calculated values
  2. The values should be calculated from the modified document-node() (that is what the $extractMainVersion contains)

So I added three modes. Two of them I added to the identity transform template (originally, it was set to #all). This is basic.xsl:

   <xsl:stylesheet exclude-result-prefixes="xs xd mei dme map" version="3.0" xmlns:dme="http://www.mozarteum.at/ns/dme" xmlns:map="http://www.w3.org/2005/xpath-functions/map" xmlns:mei="http://www.music-encoding.org/ns/mei" xmlns:xd="http://www.oxygenxml.com/ns/doc/xsl" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xpath-default-namespace="http://www.music-encoding.org/ns/mei">

        <xsl:output encoding="UTF-8" indent="yes" method="xml"/>
        <xsl:strip-space elements="*"/>

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

    </xsl:stylesheet>

Upvotes: 0

Michael Kay
Michael Kay

Reputation: 163458

As far as I can tell from the code fragments supplied, you have not defined any "fallback" template for the mode checkAccidentalsVisibility, therefore when you apply-templates to a document node in this mode, the built-in template rules kick in, and the default rule for elements uses apply-templates to process the children of the element but not its attributes. So attributes don't get processed.

Upvotes: 1

oleksii.sapov-erlinger
oleksii.sapov-erlinger

Reputation: 412

When explicitly passing the attributes to the @select they are matched. So,:

<xsl:apply-templates  mode="checkAccidentalsVisibility" select="$extractMainVersion//@accid"/>

matches here:

<xsl:template match="body//@accid[not(parent::accid/@func[. = 'caution'] or ancestor::note[@grace])]" mode="checkAccidentalsVisibility">

@Martin Honnen: $extractMainversion contains a document-node with the value <#documentfragment> which is almost the same as the XML snippet above. The $checkAccidentalsVisibility was previously containing a string derived from //title/text() Probably I didn't describe it well.

Although I solved the problem, I'd be interested, why you cannot match the @attributes in the way as you would normally do it without modes?

Upvotes: 0

Related Questions