我的(简化的)输入 XML 文件包含以下内容:
<?xml version="1.0" encoding="UTF-8"?>
<main>
<DATA_RECORD>
<MESSAGE><pd> <cdhead version="13"/> </pd></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><pd>
<cdhead version="13"/>
</pd></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 表达式。事实证明,虽然<
等被解析成<
等等,但这还不足以得出正确的 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 ('<pd> <cdhead version="13"/> </pd>'));
//doc.loadXML (unescapeXML (input.text));
return doc;
};
function unescapeXML (str) {
var ostr = str;
ostr = ostr.replace (/"/g, '"');
ostr = ostr.replace (/</g, '<');
ostr = ostr.replace (/=/g, '=');
ostr = ostr.replace (/>/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 ('<pd> <cdhead version="13"/> </pd>'));
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><pd> <cdhead version="13"/> </pd></MESSAGE>
</DATA_RECORD>
</main>
当我在 IE9 中打开这个文件时(其中 test.xslt 是转换的版本,其中输入被忽略,而是处理文字,因此在 XML Spy 中是可以的),我得到一个处理错误:
XML5001: Applying Integrated XSLT Handling.
XSLT8690: XSLT processing failed.
为什么这一切,我该如何纠正?