Andrei
Andrei

Reputation: 43

What expression to use with xsl:value-of to select text value from certain elements

I have this kind of XML structure and I need to print out what both paragraph sections contains. How to do that? Basically I thought about for-each loop, but what to put inside xsl:value-of construction? Thanks!

   <slideshow>
        <slide id="A1">
            <title>XML techniques</title>
            <paragraph> Slideshow prepresents different kind of <bold>XML</bold> techniques </paragraph>
            <paragraph> Most common XML Techniques are </paragraph>

Upvotes: 1

Views: 3600

Answers (2)

Abel
Abel

Reputation: 57159

You wrote:

Basically I thought about for-each loop,

When processing nodes, a xsl:for-each is rarely necessary. Use xsl:apply-templates selecting the nodes you want. Without a matching template, this will spit out the values of the nodes (the text) by default:

<xsl:template match="slide">
    <!-- just process selection of children -->
    <xsl:apply-templates select="paragraph" />
</xsl:template>

<!-- add this in case you already have an identity template -->
<xsl:template match="paragraph">
    <!-- select only the immediate text children (without <b> for instance) -->
    <xsl:value-of select="text()" />
    <!-- OR: select the value, incl. all children (using "node()" is equiv.) -->
    <xsl:value-of select="." />
</xsl:template>

And you wrote:

but what to put inside xsl:value-of construction? Thanks!

This greatly depends on the focus. Focus is typically set by the first ancestor instruction xsl:template or xsl:for-each. Suppose your focus is on <slideshow>, the expression would be:

<xsl:value-of select="slide/paragraph" />

If the focus is already on paragraph, you can use select="text()" (selects all text children, but not deeper), or select="." (selects current node, takes value of children as well).

But see above for a more resilient approach. Using apply-templates makes it easier to code for change and maintainability.

Upvotes: 2

user52889
user52889

Reputation: 1501

Assuming your XSLT looks something like

<xsl:for-each select="//paragraph">
  ???
</xsl:for-each>

You could write:

<xsl:for-each select="//paragraph">
  <xsl:copy-of select="node()"/>
</xsl:for-each>

... this would return a copy of the nodes - text and elements - that are children of the paragraph.

Depending on what other rules you have and want to execute, you could also write:

<xsl:for-each select="//paragraph">
  <xsl:apply-templates select="node()"/>
</xsl:for-each>

... this would also return a copy of the nodes - text and elements - that are children of the paragraph, unless you've got other templates overriding that behaviour.

If all you wanted was the raw text in each paragraph (i.e. without the bold tags), you could use a value-of.

<xsl:for-each select="//paragraph">
  <xsl:value-of select="."/>
</xsl:for-each>

If that's all you're doing, you could even write it as:

<xsl:value-of select="//paragraph"/>

(Note: I give //paragraph as an example because no context is provided but probably you want to be going through the slides and selecting the paragraph children).

Upvotes: 2

Related Questions