1

from outside i'd like to pass a certain variable into an XSL (here no prob) and use it as an expression in the attribute "select" of a xsl:for-each element (the prob).

The following code (simplified, implemented in proper xml, stylesheet etc. elements) will NOT work, (but hopefully illustrates the task to do; injected is by example the string "books/book" assigned to param name searchstring)

...
<xsl:param name="searchstring" /> 

 <xsl:template match="/">
   <xsl:for-each select="$searchstring">
    <xsl:value-of select="title" />
   </xsl:for-each>
 </xsl:template>
...

because the "injected" param value is a string and will not bound to a result tree fragment, what is obviously expected by the "select" attribute. After a "full beard"-period of unsuccsessful research, I'd be very happy to find a way on ... how can this param value be turned into a fitting select expression?

best regards and thx already

2 Answers2

1

If you really need to pass in an XPath expression to be dynamically evaluated then you need XSLT 3.0 which has http://www.w3.org/TR/xslt-30/#element-evaluate or you need to check whether you preferred XSLT 1.0 or 2.0 processor offers an extension function like http://exslt.org/dyn/functions/evaluate/index.html. A different approach is to write a stylesheet that generates a second stylesheet, that way you can put your path parameter(s) in the place(s) you need them.

Martin Honnen
  • 160,499
  • 6
  • 90
  • 110
  • Thx for the quick response. It seems with regular XSLT1.0 -> no way out. – Boris Hoeller May 16 '15 at 12:05
  • @BorisHoeller Not necesarily. – michael.hor257k May 16 '15 at 12:08
  • certainly I will try to work around e.g. using SimpleXML in the php script calling the xsl, but all the work in the xsl file turned kind of redundant, spreading sadness ;) – Boris Hoeller May 16 '15 at 12:13
  • @BorisHoeller, regular XSLT 1.0 can certainly take the approach of having one stylesheet with path parameters create a second stylesheet with path expressions in the right place which can then be executed. And depending on (the lack of) the complexity of your path parameters there might be ways to break them up in XSLT 1.0 and select the nodes. But if you need to evaluate arbitrary path expression dynamically at runtime in a single stylesheet then you need an extension. – Martin Honnen May 16 '15 at 12:13
  • At this time, this summary: On the basis of pure XSLT1.0 in one file, without producing "secondary" XSL files, one is stuck. For me a good help, using my time for different solution to the problem from now on. Thx again! – Boris Hoeller May 16 '15 at 12:35
  • @BorisHoeller "*On the basis of pure XSLT1.0 in one file, without producing "secondary" XSL files, one is stuck.*" No, not necessarily (2). – michael.hor257k May 16 '15 at 12:45
  • so there is also a mystic component in the answer to my question (I'm almost done using SimpleXML methods ($searchstring is defined by php script and results in "$xml->xpath($searchstring)") instead of calling an xsl file passing the string through to achieve the goal aimed for, so 4me the whole question becomes more and more academic, but it was worth raising it up - is there a solution? ) – Boris Hoeller May 16 '15 at 14:18
0

If you are able to put some restrictions on the type of paths that will be passed as a parameter, then this can be done using a single XSLT 1.0 stylesheet.

It's too bad you refused to provide an example, forcing me to make up my own:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:param name="path"/>

<xsl:template match="/">
    <selected-nodes>
        <xsl:apply-templates/>
    </selected-nodes>
</xsl:template>

<xsl:template match="*">
    <xsl:variable name="path-to-me">
        <xsl:for-each select="ancestor-or-self::*">
            <xsl:value-of select="concat('/', name())"/>
        </xsl:for-each>    
    </xsl:variable>
    <xsl:if test="$path-to-me=$path">
        <xsl:copy-of select="."/>
    </xsl:if>
    <xsl:apply-templates select="*"/>
</xsl:template>

</xsl:stylesheet>

XML

<book>
    <chapter>
        <title>Chapter One</title>
        <section>
            <title>First Section</title>
                <subsection>
                    <title>Alpha</title>
                </subsection>
                <subsection>
                    <title>Bravo</title>
                </subsection>
                <subsection>
                    <title>Charlie</title>
                </subsection>
        </section>
        <section>
            <title>Second Section</title>
                <subsection>
                    <title>Delta</title>
                </subsection>
                <subsection>
                    <title>Echo</title>
                </subsection>
        </section>
    </chapter>      
    <chapter>
        <title>Chapter Two</title>
        <section>
            <title>Third Section</title>
                <subsection>
                    <title>Foxtrot</title>
                </subsection>
                <subsection>
                    <title>Golf</title>
                </subsection>
        </section>
        <section>
            <title>Fourth Section</title>
                <subsection>
                    <title>Hotel</title>
                </subsection>
                <subsection>
                    <title>India</title>
                </subsection>
                <subsection>
                    <title>Juliet</title>
                </subsection>
        </section>
    </chapter>      
</book>

Parameter

$path = "/book/chapter/section/title"

Result

<?xml version="1.0" encoding="UTF-8"?>
<selected-nodes>
   <title>First Section</title>
   <title>Second Section</title>
   <title>Third Section</title>
   <title>Fourth Section</title>
</selected-nodes>

Constraints:

  1. The parameter passed must be a full absolute path to an element (although the method could be expanded to include other node types);
  2. No predicates are allowed (although the method could be expanded to include numerical predicates);
  3. It is assumed that the source XML nodes are in no namespace.
michael.hor257k
  • 113,275
  • 6
  • 33
  • 51
  • thx a lot for this (I'm very sorry, I did not observe your request for code + your solution until now) - it looks like, the issue has been solved by you. Again thank you very much for this achievement! – Boris Hoeller May 16 '15 at 14:34