0

I'm trying to execute a set of given xpaths that are stored in a variable using XSLT 1.0. While accessing the list of xpaths using for-each inside the template, the context changes and thus unable to extract any xpath value from the original xml. It simply returns blank value.

Input xml:

<catalog>
    <book id="bk101">
        <author>Gambardella Matthew</author>
        <title>XML Developer's Guide</title>
        <genre>Computer</genre>
        <price>44.95</price>
        <publish_date>2000-10-01</publish_date>
    </book>
    <book id="bk102">
        <author>Ralls Kim</author>
        <title>Midnight Rain</title>
        <genre>Fantasy</genre>
        <price>5.95</price>
    </book>
</catalog>

XSLT I tried:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:dyn="http://exslt.org/dynamic" xmlns:exsl="http://exslt.org/common" version="1.0" exclude-result-prefixes="dyn exsl">
  <xsl:variable name="newLine" select="'&#xA;'" />
  <xsl:variable name="comma" select="','" />
  <xsl:variable name="details">
    <xpaths>
      <xpath>/catalog/book/author</xpath>
      <xpath>/catalog/book/title</xpath>
      <xpath>/catalog/book/genre</xpath>
      <xpath>/catalog/book/price</xpath>
      <xpath>/catalog/book/publish_date</xpath>
    </xpaths>
  </xsl:variable>
  <xsl:template match="/">
    <xsl:apply-templates select="*" mode="extract" />
  </xsl:template>
  <xsl:template match="book" mode="extract">
    <xsl:if test="position() !=1">
      <xsl:value-of select="$newLine" />
    </xsl:if>
    <xsl:for-each select="exsl:node-set($details)/xpaths/xpath">
      <xsl:if test="position() ! =1" />
      <xsl:value-of select="$comma" />
      <xsl:variable name="this" select="." />
      <xsl:value-of select="dyn:evaluate($this)" />
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>

The output I'm expecting is:

Gambardella Matthew,XML Developer's Guide,Computer,44.95,2000-10-01
Ralls Kim,Midnight Rain,Fantasy,5.95,,

The output above xslt produces:

,,,,,
,,,,,

Can someone give a clue on the required XSLT 1.0 please? Thank you in advance.

1 Answer 1

1

I don't think the absolute XPath expressions you have used make sense in the context of a book element, you would need to use relative paths. Then you can change the context to the book as follows:

<xsl:variable name="details">
    <xpaths>
        <xpath>author</xpath>
        <xpath>title</xpath>
        <xpath>genre</xpath>
        <xpath>price</xpath>
        <xpath>publish_date</xpath>
    </xpaths>
</xsl:variable>
<xsl:template match="/">
    <xsl:apply-templates select="*" mode="extract" />
</xsl:template>
<xsl:template match="book" mode="extract">
    <xsl:if test="position() !=1">
        <xsl:value-of select="$newLine" />
    </xsl:if>
    <xsl:variable name="book" select="."/>
    <xsl:for-each select="exsl:node-set($details)/xpaths/xpath">
        <xsl:if test="position() != 1">
            <xsl:value-of select="$comma" />
        </xsl:if>
        <xsl:variable name="path" select="." />
        <xsl:for-each select="$book"><xsl:value-of select="dyn:evaluate($path)" /></xsl:for-each>
    </xsl:for-each>
</xsl:template>

Obviously if you simply use $book/*[local-name() = $path] you would get it to work without using the usually unsupported dyn:evaluate.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.