1

我的(简化的)输入 XML 文件包含以下内容:

<?xml version="1.0" encoding="UTF-8"?>
<main>
    <DATA_RECORD>
        <MESSAGE>&#60;pd&#62;&#10;    &#60;cdhead version&#61;&#34;13&#34;/&#62;&#10;&#60;/pd&#62;</MESSAGE>
    </DATA_RECORD>
</main>

MESSAGE 元素值是一个字符转义的 XML 实例。它表示以下 XML:

<pd>
    <cdhead version="13"/>
</pd>

我想对输入 XML 应用 xsl 转换,并以某种方式将 MESSAGE 内容解析为变量并使用 Xpath 表达式来访问其详细信息。
我尝试如下添加一个 javascript 函数,但脚本返回的对象显然是不正确的 DOM 子类(请参见下面的结果)。为了完整起见,我添加了一个额外的函数,它将 DOM 内容作为字符串返回。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:ms="urn:schemas-microsoft-com:xslt"
    xmlns:my="http://example.com/my"
    exclude-result-prefixes="ms my">

    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

    <ms:script language="JScript" implements-prefix="my">
        <![CDATA[
        function parseToDOM (input) {
        var doc = new ActiveXObject('Msxml2.DOMDocument.6.0');
        doc.loadXML (input);
        return doc.documentElement;
        };
        function parseToXMLString (input) {
        var doc = new ActiveXObject('Msxml2.DOMDocument.6.0');
        doc.loadXML (input);
        return doc.documentElement.xml;
        };
        ]]>
    </ms:script>

    <xsl:template match="/">
        <root>
            <xsl:apply-templates/>
        </root>
    </xsl:template>

    <xsl:template match="DATA_RECORD">
            <xsl:variable name="DOM"><xsl:copy-of select="my:parseToDOM (MESSAGE)"/></xsl:variable>
            <xsl:variable name="XML"><xsl:copy-of select="my:parseToXMLString (MESSAGE)"/></xsl:variable>

            <msg1><xsl:value-of select="$XML"/></msg1>
            <msg2><xsl:value-of select="$XML" disable-output-escaping="yes"/></msg2>
            <dom><xsl:copy-of select="$DOM"/></dom>
            <version><xsl:value-of select="$DOM/pd/cdhead/@version"/></version>
    </xsl:template>

    <xsl:template match="text()"/>
</xsl:stylesheet>

结果:

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <msg1>&lt;pd&gt;
    &lt;cdhead version="13"/&gt;
&lt;/pd&gt;</msg1>
    <msg2><pd>
    <cdhead version="13"/>
</pd></msg2>
    <dom/>
    <version></version>
</root>

如何使 Jscript 函数返回允许使用 Xpath 的结果?
顺便说一句,是否有一些 XSLT 1.0 函数允许将转义的 XML 字符串解析为允许使用 Xpath 的结果?

添加

我一直在尝试一些变化并更接近解决方案。首先,Altova XMLSpy 允许选择 xsl 处理器,使用内置处理器时会出现上述情况。当然,我需要MSXML 6.0,并且在选择一个时,错误会出现错误,因为我不得不解析Input.text。但是我只是在 javascript 中做了额外的事情之后才成功地在结果中使用了 Xpath 表达式。事实证明,虽然&#60;等被解析成&lt;等等,但这还不足以得出正确的 DOM 结果。所以我首先求助于对输入字符串进行转义。
但是我遇到了另一个障碍:下面的工作正常,当我使用input.text而不是下面的文字时它就不行了。

请参阅下面的 xslt。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:ms="urn:schemas-microsoft-com:xslt"
    xmlns:my="http://example.com/my"
    exclude-result-prefixes="ms my">

    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

    <ms:script language="JScript" implements-prefix="my">
        <![CDATA[
        function parseToDOM (input) {
            var doc = new ActiveXObject('Msxml2.DOMDocument.6.0');
            doc.loadXML (unescapeXML ('&#60;pd&#62;&#10;    &#60;cdhead version&#61;&#34;13&#34;/&#62;&#10;&#60;/pd&#62;'));
            //doc.loadXML (unescapeXML (input.text));
            return doc;
        };
        function unescapeXML (str) {
            var ostr = str;
            ostr = ostr.replace (/&#34;/g, '"');
            ostr = ostr.replace (/&#60;/g, '<');
            ostr = ostr.replace (/&#61;/g, '=');
            ostr = ostr.replace (/&#62;/g, '>');
            return ostr;
        };
        ]]>
    </ms:script>

    <xsl:template match="/">
        <root>
            <xsl:apply-templates/>
        </root>
    </xsl:template>

    <xsl:template match="DATA_RECORD">
        <xsl:variable name="msg" select="my:parseToDOM (MESSAGE)"/>
        <tst><xsl:value-of select="$msg/pd/cdhead/@version"/></tst>
   </xsl:template>

</xsl:stylesheet>

现在结果

<?xml version="1.0" encoding="UTF-8"?>
<root>
<tst>13</tst>
</root>

这正是我想要的。

但如上所述,当我评论文字的解析并改用输入时,如下所示:

//doc.loadXML (unescapeXML ('&#60;pd&#62;&#10;    &#60;cdhead version&#61;&#34;13&#34;/&#62;&#10;&#60;/pd&#62;'));
doc.loadXML (unescapeXML (input.text));

我收到以下错误(在 Altova XML Spy 中使用 MSXML 6.0 作为 xslt 解析器):

XSL transformation failed due to following error:

Microsoft JScript runtime error
'undefined' is null or not an object
line = 10, col = 3 (line is offset from the start of the script block).
Error returned from property or method call.

这指向第一个 javascript 替换语句。

此外,IE9 无法正确处理以下内容:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="test.xslt"?>
<main>
  <DATA_RECORD>
    <MESSAGE>&#60;pd&#62;&#10;    &#60;cdhead version&#61;&#34;13&#34;/&#62;&#10;&#60;/pd&#62;</MESSAGE>
  </DATA_RECORD>
 </main>

当我在 IE9 中打开这个文件时(其中 test.xslt 是转换的版本,其中输入被忽略,而是处理文字,因此在 XML Spy 中是可以的),我得到一个处理错误:

XML5001: Applying Integrated XSLT Handling. 
XSLT8690: XSLT processing failed. 

为什么这一切,我该如何纠正?

4

1 回答 1

2

从上面的添加开始,我通过微调得到了一个解决方案。
为了避免不得不这样做input.text并使用plain ,xsl 必须通过应用xslt stringinput函数来包含元素到字符串的转换(我认为它已经是一个字符串,但显然情况并非如此)。此外,现在不再需要应用替换语句。 因此

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:ms="urn:schemas-microsoft-com:xslt"
    xmlns:my="http://example.com/my"
    exclude-result-prefixes="ms my">

    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

    <ms:script language="JScript" implements-prefix="my">
        <![CDATA[
        function parseToDOM (input) {
            var doc = new ActiveXObject('Msxml2.DOMDocument.6.0');
            doc.loadXML (input);
            return doc;
        };
        ]]>
    </ms:script>

    <xsl:template match="/">
        <root>
            <xsl:apply-templates/>
        </root>
    </xsl:template>

    <xsl:template match="DATA_RECORD">
        <xsl:variable name="msg" select="my:parseToDOM (string(MESSAGE))"/>
        <tst><xsl:value-of select="$msg/pd/cdhead/@version"/></tst>
   </xsl:template>

</xsl:stylesheet>

作品:当应用于

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="test.xslt"?>
<main>
  <DATA_RECORD>
    <MESSAGE>&#60;pd&#62;&#10;    &#60;cdhead version&#61;&#34;13&#34;/&#62;&#10;&#60;/pd&#62;</MESSAGE>
  </DATA_RECORD>
 </main>

结果是

<?xml version="1.0" encoding="UTF-8"?>
<root>
<tst>13</tst>
</root>

不幸的是,IE9 仍然无法使用引用的 XSLT 加载 XML;我发现了原因。
我必须勾选 Internet 选项/高级/安全/允许活动内容在我的电脑上的文件中运行 - 并重新启动 IE - 这使得 IE9 可以正确处理文件。当然,结果不是 html 意味着只能在 F12/Script 选项卡中查看结果,但这只是一个示例,我会将其合并到生成正确 html 的 xslt 中。

于 2013-02-18T11:55:44.987 回答