Search code examples
xsltkeytei

Copy over an XSLT attribute based on another attribute


It seems to me that this should be an easy thing to do with key but I'm struggling.

I have two XML files with <w> elements with <m> elements within.

They both have a @corresp attribute and a @sameAs attribute, but one of the files has is missing a number of the @sameAs attributes.

I would like to copy over the missing @sameAs attributes from one file to the other with the assumption that the @sameAs value is paired with the @corresp attribute's value (they are English/Spanish translations).

Where a value for @sameAs already exists, I this should not be overwritten.

The @sameAs - @corresp pairs are valid across both m and w.

The input file looks like this:

<p>
    <w  pos="N" corresp="house" sameAs="casa/ruca"><m corresp="house"  sameAs="casa" type="root">ruca</m></w>
    <w  pos="N" corresp="man"><m corresp="man" type="root">wentru</m></w>
    <w  pos="AJ" corresp="bad"><m corresp="bad" type="root">weda</m></w>
    <w  pos="N" corresp="query"><m corresp="stone/rock" sameAs="piedra/roca" type="root">cura</m><m corresp="instrumental" type="suffix">we</m></w>
</p>

The output should be:

<p>
    <w  pos="N" corresp="house" sameAs="casa/ruca"><m corresp="house" sameAs="casa" type="root">ruca</m></w>
    <w  pos="N" corresp="man"  sameAs="hombre"><m corresp="man" sameAs="hombre" type="root">wentru</m></w>
    <w  pos="AJ" corresp="bad"  sameAs="malo(a)"><m corresp="bad" type="root" sameAs="malo(a)">weda</m></w>
    <w  pos="N" corresp="query"><m corresp="stone/rock" sameAs="piedra/roca" type="root">kura</m><m corresp="instrumental" type="suffix">we</m></w>
</p>

The lookup file looks like this:

<p>
    <w  pos="N" corresp="house" sameAs="casa"><m corresp="house"  sameAs="casa" type="root">ruka</m></w>
    <w  pos="N" corresp="dog" sameAs="perro"><m corresp="dog"  sameAs="perro" type="root">txewa</m></w>
    <w  pos="N" corresp="man"  sameAs="hombre"><m corresp="man"  sameAs="hombre" type="root">wentro</m></w>
    <w  pos="AJ" corresp="bad"  sameAs="malo(a)"><m corresp="bad" type="root" sameAs="malo(a)">wesha</m></w>
    <w  pos="N" corresp="query"><m corresp="stone/rock" sameAs="piedra/roca" type="root">kura</m><m corresp="instrumental" type="suffix">we</m></w>
</p>

I tried the following, but to no avail:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xpath-default-namespace="http://www.tei-c.org/ns/1.0"
    exclude-result-prefixes="#all"
    version="3.0">
    <xsl:param name="lookup-doc" select="document('lookup.xml')"/>
    <xsl:key name="ref" match="w/@sameAs|node()" composite="yes" use="@corresp"/>
    <xsl:mode on-no-match="shallow-copy"/> 
    <xsl:template match="w/@sameAs|node()[key('ref', (@corresp, @sameAs), $lookup-doc)]">
        <xsl:copy-of select="w/@sameAs|node()[key('ref', (@corresp, @sameAs), $lookup-doc)]"/>
    </xsl:template>
</xsl:stylesheet>

Any tips?


Solution

  • The textual description to copy sameAs attributes if they don't exist sounds like

    <xsl:key name="ref" match="w" use="@corresp"/>
    
    <xsl:mode on-no-match="shallow-copy"/> 
    
    <xsl:template match="w[not(@sameAs)][key('ref', @corresp, $lookup-doc)] | m[not(@sameAs)][key('ref', @corresp, $lookup-doc)]">
        <xsl:copy>
          <xsl:apply-templates select="@*, key('ref', @corresp, $lookup-doc)/@sameAs, node()"/>
        </xsl:copy>
    </xsl:template>