F.Capoccia
F.Capoccia

Reputation: 105

XSLT How to select only the value of an element with children

I have this code and can't edit it:

<elenco-treni>
<treno id='1'> Moderno
    <percorso>Terni - Spoleto</percorso>
    <tipo genere='locale'> aaa
        <fermata>Narni</fermata>
        <fermata informale='s'>Giano</fermata>
    </tipo>
</treno>

<treno id='5' codice='G140'> Jazz
    <percorso>Orte - Terontola</percorso>
    <tipo genere='regionale'>
        <fermata>Terni</fermata>
        <fermata>Spoleto</fermata>
        <fermata>Foligno</fermata>
        <fermata>Assisi</fermata>
        <fermata>Perugia</fermata>
    </tipo>
</treno>
</elenco-treni>

and I got some problems:

  1. When I select "elenco-treni", everything doesn't work
<xsl:for-each select="elenco-treni">
<xsl:value-of select="treno"/>

gives me blank result.

  1. I can't get the value of tipo which is "aaa"
<xsl:for-each select="treno">
<xsl:value-of select="tipo"/>

gives me all of "tipo" children and it's value.

Upvotes: 0

Views: 132

Answers (1)

Michael Kay
Michael Kay

Reputation: 163302

This is badly designed XML, in that it is using mixed content (elements that have both text nodes and other elements as children) in a way that mixed content wasn't designed to be used. Constructs like xsl:value-of work well if mixed content is used properly, but they don't work well on this kind of input.

When you're dealing with badly designed XML, the best thing is to start by transforming it to something cleaner. You could do this here with a transformation that wraps the text nodes in an element:

<xsl:template match="treno/text()[normalize-space(.)]">
  <veicolo><xsl:value-of select="normalize-space(.)"/></veicolo>
</xsl:template>

This takes care only to wrap the non-whitespace text nodes.

Upvotes: 1

Related Questions