使用 XSLT output-method="text" 转换插入的意外转义 CR
Unexpected escaped CRs inserted with XSLT output-method="text" transform
我的问题是以下行为的逻辑可能是什么,或者如果它是一个错误(在 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[
]]>">]> <!-- (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>
但是,我得到的输出包括无关的转义 CR,在每行的末尾按字面意思输出为 " "
。
first item
second item
问题又是关于上面的特定行为,我觉得这很奇怪。我特别不要求替代方案或解决方法,事实上,它们的变体看起来工作正常。
<!DOCTYPE xsl:stylesheet [<!ENTITY eol "<![CDATA[
]]>">]> <!-- (b) works -->
<!DOCTYPE xsl:stylesheet [<!ENTITY eol "&#xA;">]> <!-- (c) no newlines in output -->
<!DOCTYPE xsl:stylesheet [<!ENTITY eol "&#xA;">]> <!-- (d) works -->
<!DOCTYPE xsl:stylesheet [<!ENTITY eol "
">]> <!-- (e) no newlines in output -->
<!DOCTYPE xsl:stylesheet [<!ENTITY eol "
">]> <!-- (f) works -->
[ 编辑 ] 以下是重现该问题的最小 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.xml
和test.xslt
,在cmd提示符下的转换可以是运行如下,
C:\etc>cscript //nologo test.js test.xml test.xslt
first item
second item
C:\etc>
我认为这是 MSXML 6 和 "new parser" 你用 xslDoc.setProperty("NewParser", true);
启用的错误。即使根本不使用任何 XSLT,您也可以加载
这样的文档
<!DOCTYPE root [<!ENTITY eol "<![CDATA[
]]>">]>
<root>&eol;</root>
使用 MSXML 6 和 "new parser" 并检查 root/document 元素的 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);
它显示
。
如果您还输出 WScript.Echo(xmlDoc.documentElement.firstChild.firstChild.nodeValue);
,您会得到相同的值,因此实体解析最终会 "converting" 来自 DTD 子集的 <!ENTITY eol "<![CDATA[
]]>">
和 &eol;
包含 CDATA 节节点的实体引用节点,节点值中转义的十六进制字符引用 
现在是转义的十进制字符
.
我的问题是以下行为的逻辑可能是什么,或者如果它是一个错误(在 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[
]]>">]> <!-- (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>
但是,我得到的输出包括无关的转义 CR,在每行的末尾按字面意思输出为 " "
。
first item
second item
问题又是关于上面的特定行为,我觉得这很奇怪。我特别不要求替代方案或解决方法,事实上,它们的变体看起来工作正常。
<!DOCTYPE xsl:stylesheet [<!ENTITY eol "<![CDATA[
]]>">]> <!-- (b) works -->
<!DOCTYPE xsl:stylesheet [<!ENTITY eol "&#xA;">]> <!-- (c) no newlines in output -->
<!DOCTYPE xsl:stylesheet [<!ENTITY eol "&#xA;">]> <!-- (d) works -->
<!DOCTYPE xsl:stylesheet [<!ENTITY eol "
">]> <!-- (e) no newlines in output -->
<!DOCTYPE xsl:stylesheet [<!ENTITY eol "
">]> <!-- (f) works -->
[ 编辑 ] 以下是重现该问题的最小 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.xml
和test.xslt
,在cmd提示符下的转换可以是运行如下,
C:\etc>cscript //nologo test.js test.xml test.xslt
first item
second item
C:\etc>
我认为这是 MSXML 6 和 "new parser" 你用 xslDoc.setProperty("NewParser", true);
启用的错误。即使根本不使用任何 XSLT,您也可以加载
<!DOCTYPE root [<!ENTITY eol "<![CDATA[
]]>">]>
<root>&eol;</root>
使用 MSXML 6 和 "new parser" 并检查 root/document 元素的 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);
它显示
。
如果您还输出 WScript.Echo(xmlDoc.documentElement.firstChild.firstChild.nodeValue);
,您会得到相同的值,因此实体解析最终会 "converting" 来自 DTD 子集的 <!ENTITY eol "<![CDATA[
]]>">
和 &eol;
包含 CDATA 节节点的实体引用节点,节点值中转义的十六进制字符引用 
现在是转义的十进制字符
.