使用XSLT output-method =“ text”转换插入意外的转义CR

时间:2019-04-21 04:02:55

标签: xml xslt msxml msxml6

我的问题是,以下行为的逻辑可能是什么,或者它是否是一个错误(在Windows下的MSXML6中),甚至是什么逻辑故障也会导致这种错误。

考虑输入的XML文件。

<?xml version="1.0" encoding="utf-8"?>
<root>
    <item>first item</item>
    <item>second item</item>
</root>

下面的XSLT尝试以文本格式(每行一个,以标准Windows CR-LF行结尾)提取项目。

<?xml version="1.0" encoding="utf-8"?>

<!DOCTYPE xsl:stylesheet [<!ENTITY eol "<![CDATA[&#xD;&#xA;]]>">]> <!-- (a) !?? -->

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="text" version="1.0" encoding="utf-8" media-type="text/plain"/>
<xsl:strip-space elements='*'/>
<xsl:template match="item"> <!-- list items, one per line -->
    <xsl:value-of select="."/>
    <xsl:text disable-output-escaping="yes">&eol;</xsl:text>
</xsl:template>
</xsl:stylesheet>

但是,我得到的输出包括在每行末尾以"&#13;"的形式输出的多余的转义CR。

first item&#13;
second item&#13;

问题还是关于上述特定行为,我觉得这很奇怪。我明确地不要求替代方案或变通办法,实际上,它们的变体看起来可以正常工作。

<!DOCTYPE xsl:stylesheet [<!ENTITY eol "<![CDATA[&#xA;]]>">]> <!-- (b) works  -->
<!DOCTYPE xsl:stylesheet [<!ENTITY eol "&amp;#xA;">]>         <!-- (c) no newlines in output -->
<!DOCTYPE xsl:stylesheet [<!ENTITY eol "&#x26;#xA;">]>        <!-- (d) works  -->
<!DOCTYPE xsl:stylesheet [<!ENTITY eol "&#xA;">]>             <!-- (e) no newlines in output -->
<!DOCTYPE xsl:stylesheet [<!ENTITY eol "&#xD;&#xA;">]>        <!-- (f) works  -->


[ EDIT ]以下是重复该问题的最小JScript代码。

var vArgs = WScript.Arguments;
var xmlFile = vArgs(0);
var xslFile = vArgs(1);

var xmlDOMDocProgID = "MSXML2.DOMDocument.6.0";

var xmlDoc = new ActiveXObject(xmlDOMDocProgID);
xmlDoc.setProperty("NewParser", true);
xmlDoc.validateOnParse = false;
xmlDoc.async = false;
xmlDoc.load(xmlFile);

var xslDoc = new ActiveXObject(xmlDOMDocProgID);
xslDoc.setProperty("NewParser", true);
xslDoc.setProperty("ProhibitDTD", false);
xslDoc.validateOnParse = false;
xslDoc.async = false;
xslDoc.load(xslFile);

WScript.StdOut.Write(xmlDoc.transformNode(xslDoc));

假设将其另存为test.js,并且xml / xslt文件分别为test.xmltest.xslt,则cmd提示符下的转换可以运行为

C:\etc>cscript //nologo test.js test.xml test.xslt
first item&#13;
second item&#13;

C:\etc>

1 个答案:

答案 0 :(得分:1)

我认为这是MSXML 6和使用xslDoc.setProperty("NewParser", true);在此处启用的“新解析器”的错误。即使根本不使用任何XSLT,您都可以加载

之类的文档。
<!DOCTYPE root [<!ENTITY eol "<![CDATA[&#xD;&#xA;]]>">]>
<root>&eol;</root>

使用MSXML 6和“新解析器”,并检查根目录/文档元素的text属性

var xmlDOMDocProgID = "MSXML2.DOMDocument.6.0";

var xmlDoc = new ActiveXObject(xmlDOMDocProgID);
xmlDoc.setProperty("NewParser", true);
xmlDoc.setProperty("ProhibitDTD", false);
xmlDoc.validateOnParse = false;
xmlDoc.load('cdata-input2.xml');

WScript.Echo(xmlDoc.documentElement.text);

它显示&#13;

如果您还输出WScript.Echo(xmlDoc.documentElement.firstChild.firstChild.nodeValue);,则会得到相同的值,因此,实体解析最终将DTD子集中的<!ENTITY eol "<![CDATA[&#xD;&#xA;]]>">&eol;转换为包含以下内容的实体引用节点:一个具有节点值的CDATA节节点,其中转义的十六进制字符引用&#xD;现在是转义的十进制&#13;