XSLT:无法将操作数转换为“结果树片段”

Posted

技术标签:

【中文标题】XSLT:无法将操作数转换为“结果树片段”【英文标题】:XSLT : Cannot convert the operand to 'Result tree fragment' 【发布时间】:2011-04-27 22:21:45 【问题描述】:

我在处理一个 xslt 样式表,我应该接收两个额外的 XML 作为参数。使用 node-set() 方法(来自命名空间 ms,microsoft)时出现错误。 XML 的内容是正确的。参数使用经典 ASP 发送。

这是 xslt 中的标题和调用:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
     xmlns:ms="urn:schemas-microsoft-com:xslt"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
...
<xsl:param name="xmlPlanning"></xsl:param>
<xsl:variable name="myXml" select="ms:node-set($xmlPlanning)"></xsl:variable>
    <xsl:value-of select="ms:node-set($xmlPlanning)/*"/>

这是错误的堆栈跟踪:

[XsltException: Impossible de convertir l'opérande en 'fragment de l'arborescence résultat'.]
   System.Xml.Xsl.XsltOld.XsltFunctionImpl.ToNavigator(Object argument) +380943
   System.Xml.Xsl.XsltOld.FuncNodeSet.Invoke(XsltContext xsltContext, Object[] args, XPathNavigator docContext) +33
   MS.Internal.Xml.XPath.FunctionQuery.Evaluate(XPathNodeIterator nodeIterator) +292

[XPathException: Échec de la fonction 'ms:node-set()'.]
   MS.Internal.Xml.XPath.FunctionQuery.Evaluate(XPathNodeIterator nodeIterator) +347
   System.Xml.Xsl.XsltOld.Processor.RunQuery(ActionFrame context, Int32 key) +24
   System.Xml.Xsl.XsltOld.VariableAction.Execute(Processor processor, ActionFrame frame) +200
   System.Xml.Xsl.XsltOld.ActionFrame.Execute(Processor processor) +20
   System.Xml.Xsl.XsltOld.Processor.Execute() +82
   System.Xml.Xsl.XsltOld.Processor.Execute(TextWriter writer) +96
   System.Xml.Xsl.XslTransform.Transform(XPathNavigator input, XsltArgumentList args, TextWriter output, XmlResolver resolver) +68
   System.Xml.Xsl.XslTransform.Transform(IXPathNavigable input, XsltArgumentList args, TextWriter output, XmlResolver resolver) +43
   System.Web.UI.WebControls.Xml.Render(htmlTextWriter output) +132

这是我在参数中收到的 xml 的开头:

<?xml version="1.0" encoding="UTF-8"?>
<ArrayOfGenerationPlanningDesign xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://webservices.secureholiday.net/">
  <GenerationPlanningDesign>

我的问题可能是什么?

【问题讨论】:

好问题,+1。请参阅我的答案以获取解释和推荐的解决方案。 【参考方案1】:

如果您传递的参数已经是真正的节点集(.NET 中的 XPath 导航器或 XPathNodeIterator 或 MSXML 中的 IXMLDOMNodeList),您不需要也不能使用 @ 987654321@扩展功能。只需删除对ms:nodeset()的调用。

如果它是一个代表 XML 的字符串——那么它不应该!将此字符串解析为节点集允许的参数类型之一,然后才调用转换——使用真正的节点集。

【讨论】:

+1 表示直接路径。比在 XSLT 本身中解析字符串更好的选择。【参考方案2】:

node-set() 仅对结果文档片段 (RDF) 进行操作,但您给它一个字符串,这是完全不同的东西(即使字符串内容看起来像 XML)。

您必须做的是将字符串解析为 XML。你可以use an extension script for that。以下对我有用(在命令行上使用 msxsl.exe 进行了测试),但如果您不想使用 JScript,您可以使用 C# 或任何其他受支持的语言来做同样的事情。

<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:ms="urn:schemas-microsoft-com:xslt"
  xmlns:script="urn:my-scripts"
  exclude-result-prefixes="ms script"  
>
  <ms:script language="JScript" implements-prefix="script">
    <![CDATA[
    function stringToXml(str) 
      var xml = new ActiveXObject("MSXML2.DOMDocument.4.0");
      xml.async = false;
      xml.loadXML(str);
      return xml;
    
    ]]>
  </ms:script>

  <xsl:param name="xmlPlanning"></xsl:param>

  <xsl:variable name="myXml" select="script:stringToXml(string($xmlPlanning))" />

  <xsl:template match="/">
    <xsl:value-of select="$myXml/*" /><!-- whatever -->
  </xsl:template>

</xsl:stylesheet>

【讨论】:

我不能使用它,因为我在经典的 Asp 中:我已经使用 .NET 进行了一些测试(在我的第一篇文章中解释了我的 .net 堆栈跟踪),但最终结果有在经典的 asp 中。 @Paul:我认为你应该在你说“我不能用这个”之前尝试一下。 对不起,你是对的。我已经尝试了你的方法,但我最终选择了连接,以便只有一个 XML。这解决了我的问题。非常感谢您的帮助!【参考方案3】:

正如 Dimitre 所说,您可以使用 ms:node-set 但您必须使用 node()

<xsl:variable name="yourVariable">
        <xsl:copy-of select="/foo/bar/something/node()"/>        
</xsl:variable>

<xsl:value-of select="ms:node-set($yourVariable)/theOtherElement"/>

【讨论】:

以上是关于XSLT:无法将操作数转换为“结果树片段”的主要内容,如果未能解决你的问题,请参考以下文章

XSLT for-each 无法提取值

如何使用 XSLT 将 JSON 转换为 XML?

XSLT学习通过JavaScript转化xml

使用 XSLT 将 XML 转换为 CSV,用于在单个标记中以空格分隔的多个记录

无法使用 XSLT 转换 XML

XSLT转换无法模板匹配