Visual Studio 和 IE 之间的 XSL/JScript 行为差异

发布于 2024-11-08 22:54:38 字数 1984 浏览 1 评论 0原文

谁能告诉我为什么下面的 XSL 在 IE9 中可以顺利地转换下面的 XML,但在所有版本的 Visual Studio 中相同的转换都会失败?如果我在 IE 9 中打开 XML 文件,它会被转换并且输出符合预期,但如果我尝试在 Visual Studio 中对 XML 文件进行相同的转换(使用工具栏上的“Start XSLT”按钮),我会收到 JScriptException 操作

var node = root.nextNode();

修复似乎是更改 javascript 函数以执行以下

function test(root, attr)
{
  root.MoveNext();
  var node = root.Current;
  return node.Select("breakfast" + attr);
}

:但是这会导致 IE 中的 XSLT 转换失败!我好像赢不了了!

XSL:

<!--<?xml version="1.0"?>-->
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:user="urn:custom-scripts">
<msxsl:script language="JScript" implements-prefix="user">
  <![CDATA[
function test(root, attr)
{
  var node = root.nextNode();
  return node.selectSingleNode("breakfast" + attr);
}
]]>
</msxsl:script>
  <xsl:template match="/">
    <HTML>
      <BODY STYLE="font-family:Arial, helvetica, sans-serif; font-size:12pt;
            background-color:#EEEEEE">
          <xsl:value-of select="user:test(., '-menu')"/>
      </BODY>
    </HTML>
  </xsl:template>
</xsl:stylesheet>

目标 XML:

<?xml version='1.0'?>
<?xml-stylesheet type="text/xsl" href="simple.xsl" ?>
<breakfast-menu>
  <food>
    <name>Belgian Waffles</name>
    <price>$5.95</price>
    <description>Two of our famous Belgian Waffles 
      with plenty of real maple syrup.</description>
    <calories>650</calories>
  </food>
  <food>
    <name>Homestyle Breakfast</name>
    <price>$6.95</price>
    <description>Two eggs, bacon or sausage, toast, 
      and our ever-popular hash browns.</description>
    <calories>950</calories>
  </food>
</breakfast-menu>

Can anyone tell me why the following XSL happily transforms the XML below in IE9, but the same transform fails under all versions of Visual Studio? If I open the XML file in IE 9, it gets transformed and the output is as expected, but if I attempt the same transform on the XML file in Visual Studio (using the 'Start XSLT' button on the toolbar) I get a JScriptException saying function expected on the line

var node = root.nextNode();

The fix seems to be to change the javascript function to do the following instead:

function test(root, attr)
{
  root.MoveNext();
  var node = root.Current;
  return node.Select("breakfast" + attr);
}

But this then fails the XSLT transform in IE! I can't seem to win!

XSL:

<!--<?xml version="1.0"?>-->
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:user="urn:custom-scripts">
<msxsl:script language="JScript" implements-prefix="user">
  <![CDATA[
function test(root, attr)
{
  var node = root.nextNode();
  return node.selectSingleNode("breakfast" + attr);
}
]]>
</msxsl:script>
  <xsl:template match="/">
    <HTML>
      <BODY STYLE="font-family:Arial, helvetica, sans-serif; font-size:12pt;
            background-color:#EEEEEE">
          <xsl:value-of select="user:test(., '-menu')"/>
      </BODY>
    </HTML>
  </xsl:template>
</xsl:stylesheet>

Target XML:

<?xml version='1.0'?>
<?xml-stylesheet type="text/xsl" href="simple.xsl" ?>
<breakfast-menu>
  <food>
    <name>Belgian Waffles</name>
    <price>$5.95</price>
    <description>Two of our famous Belgian Waffles 
      with plenty of real maple syrup.</description>
    <calories>650</calories>
  </food>
  <food>
    <name>Homestyle Breakfast</name>
    <price>$6.95</price>
    <description>Two eggs, bacon or sausage, toast, 
      and our ever-popular hash browns.</description>
    <calories>950</calories>
  </food>
</breakfast-menu>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

柳若烟 2024-11-15 22:54:38

IE 使用 MSXML 作为其 XSLT 处理器(我认为 IE 9 使用 MSXML 6),而 Visual Studio 使用 XslCompiledTransform。 MSXML 和 XslCompiledTransform 公开并使用的 API 差异很大,因此不要指望针对 MSXML API 编写的扩展函数代码能够与 XslCompiledTransform 和 .NET API 一起使用。请参阅http://msdn.microsoft.com/en-us/library/wxaw5z5e。 aspx 了解当您使用扩展函数时 XSLT/XPath 类型如何映射到 .NET 类型。在您的例子中,您传入一个节点集和一个来自 XSLT 的字符串,它们映射到 .NET 中的 XPathNodeIterator 和字符串。
这是重写 .NET 扩展函数的快速尝试:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:user="urn:custom-scripts">
  <msxsl:script language="JScript" implements-prefix="user">
    <![CDATA[
function test(nodeIterator, string)
{
  nodeIterator.MoveNext();
  return nodeIterator.Current.SelectSingleNode("breakfast" + string);
}
]]>
  </msxsl:script>
  <xsl:template match="/">
    <HTML>
      <BODY STYLE="font-family:Arial, helvetica, sans-serif; font-size:12pt;
            background-color:#EEEEEE">
        <xsl:value-of select="user:test(., '-menu')"/>
      </BODY>
    </HTML>
  </xsl:template>
</xsl:stylesheet>

[编辑]
糟糕,我错过了您已经自己找到了 .NET 代码并且只想知道如何针对两个 XSLT 处理器编写代码。那很难。你的目标平台是什么,你的目标是什么,你想为 IE 编写 XSLT 但用 VS 开发吗?或者您真的需要在 IE 和 .NET 平台上使用相同的样式表吗?

以下是为两种类型的处理器编写一个扩展函数的尝试:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:user="urn:custom-scripts">
  <msxsl:script language="JScript" implements-prefix="user">
    <![CDATA[
function test(nodeSet, string)
{
  if (typeof nodeSet.nextNode !== 'undefined') {
    var node = nodeSet.nextNode();
    return node.selectSingleNode('breakfast' + string);
  }
  else if (typeof nodeSet.MoveNext !== 'undefined') {
    nodeSet.MoveNext();
    return nodeSet.Current.SelectSingleNode("breakfast" + string);
  }
}
]]>
  </msxsl:script>
  <xsl:template match="/">
    <HTML>
      <BODY STYLE="font-family:Arial, helvetica, sans-serif; font-size:12pt;
            background-color:#EEEEEE">
        <xsl:value-of select="user:test(., '-menu')"/>
      </BODY>
    </HTML>
  </xsl:template>
</xsl:stylesheet>

Well IE uses MSXML as its XSLT processor (I think IE 9 uses MSXML 6) while Visual Studio uses XslCompiledTransform. The APIs exposed by and used with MSXML and XslCompiledTransform differ vastly so don't expect extension function code written against the MSXML API to work with XslCompiledTransform and the .NET API. See http://msdn.microsoft.com/en-us/library/wxaw5z5e.aspx on how XSLT/XPath types are mapped to .NET types when you use extension functions. In your case you pass in a node-set and a string from XSLT, that maps to an XPathNodeIterator and a String in .NET.
Here is a quick attempt to rewrite your extension function for .NET:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:user="urn:custom-scripts">
  <msxsl:script language="JScript" implements-prefix="user">
    <![CDATA[
function test(nodeIterator, string)
{
  nodeIterator.MoveNext();
  return nodeIterator.Current.SelectSingleNode("breakfast" + string);
}
]]>
  </msxsl:script>
  <xsl:template match="/">
    <HTML>
      <BODY STYLE="font-family:Arial, helvetica, sans-serif; font-size:12pt;
            background-color:#EEEEEE">
        <xsl:value-of select="user:test(., '-menu')"/>
      </BODY>
    </HTML>
  </xsl:template>
</xsl:stylesheet>

[edit]
Oops, I missed that you already found the .NET code yourself and only want to know how to write code against both XSLT processors. That is difficult. What is your target platform and your aim, do you want to write XSLT for IE but develop with VS? Or do you really need to use the same stylesheet within IE and on the .NET platform?

Here is an attempt to write one extension function for both type of processors:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:user="urn:custom-scripts">
  <msxsl:script language="JScript" implements-prefix="user">
    <![CDATA[
function test(nodeSet, string)
{
  if (typeof nodeSet.nextNode !== 'undefined') {
    var node = nodeSet.nextNode();
    return node.selectSingleNode('breakfast' + string);
  }
  else if (typeof nodeSet.MoveNext !== 'undefined') {
    nodeSet.MoveNext();
    return nodeSet.Current.SelectSingleNode("breakfast" + string);
  }
}
]]>
  </msxsl:script>
  <xsl:template match="/">
    <HTML>
      <BODY STYLE="font-family:Arial, helvetica, sans-serif; font-size:12pt;
            background-color:#EEEEEE">
        <xsl:value-of select="user:test(., '-menu')"/>
      </BODY>
    </HTML>
  </xsl:template>
</xsl:stylesheet>
迟到的我 2024-11-15 22:54:38

您可能会发现 Visual Studio 中嵌入的浏览器不是 IE9。它很可能是 IE8 版本,或者可能是 IE7,具体取决于 Visual Studio 发布时哪个版本是稳定版本。

我对 XLST 的了解还不够多,无法解释它为什么不起作用,但这可能可以解释您所看到的行为差异。

You will probably find that the browser embedded into Visual Studio is not IE9. It is most likely to be a version of IE8, or maybe IE7 dependant on which was the stable version when your Visual Studio was released.

I don't really know enough about XLST to explain why it doesn't work, but this may explain the differences in the behaviour you are seeing.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文