xslt: substring-before when node contains ampersand

Viewed 29

I´m new with xslt and need to transform some xml to another schema. To avoid having ampersands in my xml, I simply need to cut the string before the first amp (if there is any in the special node). So I tried to test if there is an amp and if so, cut before amp.

The XML looks like this:

    <record>
      <field MIDAS="#DocumentKey">obj     00004348</field>
      <field MIDAS="#5000">00004348</field>
      <field MIDAS="#5001"/>
      <field MIDAS="#5007[0]"/>
      <field MIDAS="#5007[0].5008"/>
      <field MIDAS="#5060[0]">Herstellung</field>
      <field MIDAS="#5060[0].5064">1948-1956 &amp; 1966-1968</field>
      <field MIDAS="#5060 [Umbau etc]"/>
    </record>
    <record>
      <field MIDAS="#DocumentKey">obj     00000002</field>
      <field MIDAS="#5000">00000002</field>
      <field MIDAS="#5001"/>
      <field MIDAS="#5007[0]">Teil von</field>
      <field MIDAS="#5007[0].5008">00000077</field>
      <field MIDAS="#5060[0]">Herstellung</field>
      <field MIDAS="#5060[0].5064">1904-1905</field>
      <field MIDAS="#5060 [Umbau etc]"/>
    </record>
    ...


This is my code for one of many datafields:

    <xsl:apply-templates select="field[@MIDAS='#ob45[0].4600' and .!='']"/>
...
<!--Field mappings-->
    <xsl:template match="field[@MIDAS='#ob45[0].4600']">
        <datafield tag="510" ind1=" " ind2=" ">
            <subfield code="a">
                <xsl:choose>
                    <xsl:when test="contains(field[@MIDAS='#ob45[0].4600'],'&amp;')">
                        <xsl:value-of select="substring-before('./', '&amp;')"/>
                    </xsl:when>
                    <xsl:otherwise>
                        <xsl:value-of select="."/>
                    </xsl:otherwise>
                </xsl:choose>
            </subfield>
            <subfield code="4">rela</subfield>
            <subfield code="4">https://d-nb.info/standards/elementset/gnd#relatedCorporateBody</subfield>
            <subfield code="i">In Beziehung stehende Körperschaft</subfield>
            <subfield code="9">
                <xsl:text>v:</xsl:text>
                <xsl:value-of select="../field[@MIDAS='#ob45[0] Sozietaet']"/>
            </subfield>
        </datafield>
    </xsl:template>

The result for subfield code="a": 

    <subfield code="a">1948-1956 &amp; 1966-1968</subfield>

Why does the substring-before does not work and I still have the ampersands? In some records there are amps, in other not, so I need to test.

I need:

    <subfield code="a">1948-1956</subfield>


1 Answers

Inside of any template the matched node is the context node so with <xsl:template match="field[@MIDAS='#ob45[0].4600']"> that field element is the context node, your attempt at doing <xsl:when test="contains(field[@MIDAS='#ob45[0].4600'],'&amp;')"> tries to select a field child element of the context item, which would only make sense if your fields were nested.

So you simply want <xsl:when test="contains(.,'&amp;')"> and of course then process e.g. <xsl:value-of select="substring-before(., '&amp;')"/> and not <xsl:value-of select="substring-before('./', '&amp;')"/> (which tries to apply substring-before on the string literal './').

Related