What does expression must evaluate to a node set mean?

1

I have the following code.

 <!-- Error func -->
 <xsl:template name="myFunc">
    <xsl:param name="person"/>
    <xsl:variable name="name">
       "name": "<xsl:value-of select="$person/name"/>",
    </xsl:variable>
    <xsl:value-of select="$name"/>
 </xsl:template>

 <!-- Call function -->
 <xsl:template match="/">
    <xsl:call-template name="myFunc">
        <xsl:with-param name="person" select="list/person"/>
    </xsl:call-template>
 </xsl:template>

I'm using the variable for something more complicated, but so far I can't even get this little bit to work. Is there any reason why? I keep getting the following error

System.Xml.Xsl.XslTransformException
  HResult=0x80131942
  Message=Expression must evaluate to a node-set.
  Source=System.Private.Xml
  StackTrace:
   at System.Xml.Xsl.Runtime.XsltConvert.EnsureNodeSet(IList`1 listItems)
   at System.Xml.Xsl.XmlILCommand.Execute(Object defaultDocument, XmlResolver dataSources, XsltArgumentList argumentList, XmlSequenceWriter results)
   at System.Xml.Xsl.XmlILCommand.Execute(Object defaultDocument, XmlResolver dataSources, XsltArgumentList argumentList, XmlWriter writer)
   at System.Xml.Xsl.XslCompiledTransform.Transform(IXPathNavigable input, XsltArgumentList arguments, XmlWriter results, XmlResolver documentResolver)
   at System.Xml.Xsl.XslCompiledTransform.Transform(IXPathNavigable input, XsltArgumentList arguments, XmlWriter results)
   at WZDxConversion.Controllers.ValuesController.Post() in --------------------------------------------------------
   at Microsoft.Extensions.Internal.ObjectMethodExecutor.Execute(Object target, Object[] parameters)
   at Microsoft.AspNetCore.Mvc.Internal.ActionMethodExecutor.SyncObjectResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeActionMethodAsync>d__12.MoveNext()
xml
xslt
xslt-1.0
asked on Stack Overflow Jan 3, 2020 by SA3709 • edited Jan 3, 2020 by SA3709

1 Answer

2

I'm not sure why you're getting the error with this code fragment, but I can tell you want the error message means.

When you use a path expression such as $X/Y, the expression on the left-hand-side of the "/" operator must evaluate to a node-set, which is one of the small number of basic data types in XSLT 1.0 and XPath 1.0. (There are a few other places where the value must be a node-set, but the lhs of "/" is the most common.)

When you use xsl:variable with no select attribute, for example

<xsl:variable name="v">
  <a><b/></a>
</xsl:variable>

then the value of v is not a node-set, but rather a "result tree fragment", and this means that $v cannot be used on the lhs of a "/" operator.

This was a serious design error in XSLT 1.0. James Clark explained the rationale here: https://markmail.org/message/uafk4pxqawkjuaid

What it amounts to is that the XSL WG expected that XSLT 1.0 would be quickly followed by an XSLT 1.1 that lifted such restrictions; they never expected that anyone would still be using XSLT 1.0 more than 20 years later. The restriction was of course lifted in XSLT 2.0, but Microsoft never implemented that.

answered on Stack Overflow Jan 3, 2020 by Michael Kay

User contributions licensed under CC BY-SA 3.0