1

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>
Abel
  • 56,041
  • 24
  • 146
  • 247
Andrei
  • 43
  • 1
  • 12

2 Answers2

2

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).

user52889
  • 1,501
  • 8
  • 16
  • Not quite, `node()` will select all children nodes irrespective of type, and `.` will select the current node. Depending on focus, both may include `` from the original question. – Abel Sep 26 '15 at 15:10
  • The OP asked "what to put inside xsl:value-of construction?" within a for-each - from the context I assume something similar to `` (no sample is provided). And indeed the question as asked was answered to the satisfaction of the OP. – user52889 Sep 26 '15 at 15:20
  • It is a good thing that it is to the satisfaction of the OP, but your statement is factually incorrect. Neither of your expressions will return markup. Nor will they select "just the text". – Abel Sep 26 '15 at 15:26
  • Oh, goodness, I don't know what came over me. Of course, it's total nonsense, I had confused copy-of and value-of (and I'd've been wrong even then). Clearly I've gone too long without regular interaction with XSLT. – user52889 Sep 26 '15 at 15:31
  • ... and apparently I can neither downvote my own answer nor delete it now it is accepted. Drat. – user52889 Sep 26 '15 at 15:32
  • I saw your improvements, much better :). – Abel Sep 26 '15 at 15:54
2

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.

Abel
  • 56,041
  • 24
  • 146
  • 247
  • Hm, the `text()` suggestion is subtly surprising as it returns only text children and not the text of element children. Given the use case I wouldn't put that in your main example. – user52889 Sep 26 '15 at 15:51
  • @user52889, yes, I should've been more descriptive about it. Updated. – Abel Sep 26 '15 at 15:54