j0ntech
j0ntech

Reputation: 1168

Transform XML with nested attributes using XSLT

I have an XML file with layout like this:

<root>
    <node>
        <descriptors>
            <attribute attr="important"/>
        </descriptors>
        <value>
            Some
        </value>
        <value>
            text
        </value>
        <value>
            here.
        </value>
    <node>
</root>

There are many nodes and each one is differentiated by the elements in the descriptors element. I need to extract the text so that I'd have this:

<element>
    Sometexthere.
</element>

I have an xsl transformation:

<xsl:template match="//attribute[@attr='important']">
    <element>
        <xsl:for-each select="../../value">
            <xsl:value-of select="." />
        </xsl:for-each>
    </element>
</xsl:template>

This instead just writes all the value elements in every node element in the file. I think I don't really understand the way scoping works (like when . points to the current element/node, but what is the current element/node in the loop).

How should I approach this?

EDIT

My actual xsl stylesheet (I'm transforming a docx file):

<xsl:template match="/">
        <order>
            <xsl:apply-templates/>
        </order>
    </xsl:template> 
    <xsl:template match="/w:document/w:body/w:p[w:pPr/w:pStyle/@w:val='Pealkiri1']">
        <name>
            <xsl:for-each select="w:t">
                <xsl:value-of select="." />
            </xsl:for-each>
        </name>
    </xsl:template>

Upvotes: 1

Views: 426

Answers (1)

Nils Werner
Nils Werner

Reputation: 36839

You could try matching the node element that contains descriptors/attribute/@attr=... instead of the attribute element itself.

The for-each context would then be relative to that node.

<xsl:template match="/">
    <order>
        <xsl:apply-templates select="//node[descriptors/attribute/@attr='important']" />
    </order>
</xsl:template> 

<xsl:template match="node">
    <element>
        <xsl:for-each select="value">
            <xsl:value-of select="." />
        </xsl:for-each>
    </element>
</xsl:template>

Upvotes: 2

Related Questions