tags:

views:

64

answers:

3
<xsl:apply-templates select="element[child='Yes']">

Works fine but I would like to use

<xsl:apply-templates select="element[$childElementName='Yes']">

so I can use a variable to specify the node.

For example

<xsl:apply-templates select="theList/entity[Central='Yes']">

works fine against:

<?xml version="1.0" encoding="utf-8"?>
<theList>
  <entity>
    <Business-Name>Company 1</Business-Name>
    <Phone-Number>123456</Phone-Number>
    <Central>Yes</Central>
    <region1>No</region1>
    <region2>Yes</region2>
    <region3>No</region3>
    <Northern>No</Northern>
  </entity>
  <entity>
    <Business-Name>Company 2</Business-Name>
    <Phone-Number>123456</Phone-Number>
    <Central>No</Central>
    <region1>Yes</region1>
    <region2>No</region2>
    <region3>No</region3>
    <Northern>Yes</Northern>
  </entity>
  <entity>
    <Business-Name>Company 3</Business-Name>
    <Phone-Number>123456</Phone-Number>
    <Central>Yes</Central>
    <region1>No</region1>
    <region2>No</region2>
    <region3>No</region3>
    <Northern>No</Northern>
  </entity>
  <entity>
    <Business-Name>Company 4</Business-Name>
    <Phone-Number>123456</Phone-Number>
    <Central>No</Central>
    <region1>No</region1>
    <region2>No</region2>
    <region3>No</region3>
    <Northern>No</Northern>
  </entity>
</theList>

But I do not wish to hard code the child element name.

Any suggestions?

Thanks Tim for the answer:

<xsl:apply-templates select="theList/entity[child::*[name()=$childElement]='Yes']" />
+3  A: 

You can test the name of an element using the local-name() function, like so

<xsl:apply-templates select="theList/entity[child::*[name()='Central']='Yes']" />

This checks all child nodes that have the name of 'Central'

You could then easily replace the hard-coding with a parameter or variable. Thus, if you use the following XSLT on your XML input:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;
  <xsl:param name="childElement">Central</xsl:param>
  <xsl:template match="/">
    <xsl:apply-templates select="theList/entity[child::*[name()=$childElement]='Yes']" />
  </xsl:template>
  <xsl:template match="entity">
    <Name><xsl:value-of select="Business-Name" /></Name>
  </xsl:template>
</xsl:stylesheet>

You would get the output

<Name>Company 1</Name><Name>Company 3</Name>
Tim C
@Tim C: Good answer. But, I think it must be said that with `local-name()` you select every `Central` element in any namespace (empty included). With `name()` you select every `Central` element in empty namespace or default namespace. For strict matching you must add a `namespace-uri()` condition.
Alejandro
Good point. I've changed my example to use name() instead.
Tim C
A: 

You can also use an extension to evaluate the string as an XPath expression. I've used saxon:evaluate(), but I think EXSLT also has dyn:evaluate().

Here's a sample stylesheet that uses the saxon extension:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:saxon="http://saxon.sf.net/" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;
    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:variable name="elemName" select="'Central'"/>

    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="entity[saxon:evaluate($elemName)='Yes']">
        <xsl:copy>
            <xsl:apply-templates/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="entity"/>

</xsl:stylesheet>

Output:

<?xml version="1.0" encoding="UTF-8"?>
<theList>
   <entity>
      <Business-Name>Company 1</Business-Name>
      <Phone-Number>123456</Phone-Number>
      <Central>Yes</Central>
      <region1>No</region1>
      <region2>Yes</region2>
      <region3>No</region3>
      <Northern>No</Northern>
   </entity>
   <entity>
      <Business-Name>Company 3</Business-Name>
      <Phone-Number>123456</Phone-Number>
      <Central>Yes</Central>
      <region1>No</region1>
      <region2>No</region2>
      <region3>No</region3>
      <Northern>No</Northern>
   </entity>
</theList>
DevNull
Alas, I am not using Saxon. Unfortunately I am stuck with MSXML for my sins. Thanks for your efforts.
John Hartley
A: 

Use:

theList/entity/*[name() = $childElementName][. = 'Yes']
Dimitre Novatchev