1
votes

I've been fighting this one for ages and just cannot find an answer. Files are plain text, I'm 'executing' the process in MS XmlNotePad

I'm selecting a node with XPath from an external file, but, when I try to output xsl:value-of, all I get is "true", telling me the node exists, but not the node itself.

The question is, why is my variable containing a boolean instead of the node? I've also tried not using a var, instead just putting the path in the select instead, I get the same output "true".

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  version="2.0">
  <xsl:param name="filename" select="'Elements.xml'"/>
  <xsl:param name="ele" select="document($filename)"/>

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

  <!-- find an element by id
  1. replace content inside element with value from xml filename
  2. add an element value  -->
  <xsl:template match="@*|node()">
    <!-- get element id attribute value -->      
     <xsl:copy select=".">
     <xsl:variable name="thisid" select="current()/@id"/>
     <xsl:variable name="eleNode" select="$ele//@id=$thisid"/>
     <xsl:value-of select="$thisid"/>
    <!--<xsl:attribute name="style"><xsl:value-of select="document('Elements.xml')*//@id=$thisid/@style"/></xsl:attribute>-->
    <xsl:choose>
        <xsl:when test="$eleNode">
            <xsl:value-of select="$eleNode"/>
        </xsl:when>
        <xsl:otherwise>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:otherwise>
    </xsl:choose >
     </xsl:copy>
  </xsl:template>
</xsl:stylesheet>
1
Well, $ele//@id=$thisid is a comparison expression that gives a boolean result. If you want to select elements with a certain id attribute then use $ele//*[@id = $thisid], if you want to select id attributes then use $ele//@id[. = $thisid]. - Martin Honnen
You beauty! That works great! I'll put a comment on the tutorial that told me that these were both the same thing. Are you able to 'answer' so i can mark it as correct? - Toad

1 Answers

2
votes

Well, $ele//@id=$thisid is a comparison expression that gives a boolean result. If you want to select elements with a certain id attribute then use $ele//*[@id = $thisid], if you want to select id attributes then use $ele//@id[. = $thisid].

In general, if you really use an XSLT 2 processor, it might be easier to set up a key <xsl:key name="id" match="*" use="@id"/> and simply check for the referenced node inside of the template match e.g.

<xsl:template match="*[@id and key('id', @id, $ele)]">
  <xsl:copy>
    <xsl:value-of select="key('id', @id, $ele)"/>
  </xsl:copy>
</xsl:template>

would replace the contents of any element for which the other documents contains an element of the same id with the contents of that referenced element.