2014-03-05 25 views
0

注意:最后的实际问题。带有xslt和substring的MSXML - 在换行/换行符处理不一致之前?

当我将MSXML(IE11)与libxml2/Firefox进行比较时,我在尝试通过xslt在源XML文件中尝试换行/换行符时看到的内容感到十分困惑。

从本质上讲,无论是libxml2和Firefox中实现XML End-of-Line Handling

XML解析实体通常存储在其中,用于 编辑方便,被组织成线计算机文件。这些行是 ,通常由字符CARRIAGE RETURN(#xD)和LINE FEED(#xA)的某些组合分隔。

为了简化的应用程序的任务由 平移两个二维,XML处理器必须表现 ,就好像它在归一化的输入,before parsing外部解析实体 (包括文件实体)所有换行符,字符序列#xD #xA和 后面没有#xA的单个#xA字符。现在

,看来我可以很容易地建立IE11的MSXML 不正确实现这个。

给定一个XML文件

<?xml version="1.0" encoding="utf-8"?> 
<?xml-stylesheet type="text/xsl" href="test.xsl"?> 
<root> 
    <text>We would like: 
* Free icecream 
* Free beer 
* Free linebreaks</text> 
</root> 

包含文本节点中的Windows CRLF行结束,并使用该XSL:

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

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="html" encoding="UTF-8" indent="yes"/> 

    <xsl:template match="/"> 
    <html> 
     <body> 
     <xsl:if test="contains(//text, '&#xD;&#xA;')"> 
      <p>The text contains CR+LF (0x0D+0x0A).</p> 
     </xsl:if> 
     <xsl:if test="contains(//text, '&#xD;')"> 
      <p>The text contains CR (0x0D).</p> 
     </xsl:if> 
     <xsl:if test="contains(//text, '&#xA;')"> 
      <p>The text contains LF (0x0A).</p> 
     </xsl:if> 
     </body> 
    </html> 
    </xsl:template> 

</xsl:stylesheet> 

MSXML将打印

文本包含CR + LF(0x0D + 0x0A)。

该文本包含CR(0x0D)。

该文本包含LF(0x0A)。

wheras法国法郎和libxml2的(xsltproc.exe)将只打印:

文本包含LF字符(0x0A)。

到目前为止那么糟糕。现在真正的问题是当我使用substring-beforesubstring-after来隔离换行符时。

添加此XSL:

<xsl:value-of select="'before-xA:{'"/> 
<xsl:value-of select="substring-before(//text, '&#xA;')" /> 
<xsl:value-of select="'}='"/> 
<xsl:value-of select="contains(substring-before(//text, '&#xA;'), '&#xD;')" /> 
<xsl:value-of select="'/after-xD:{'"/> 
<xsl:value-of select="substring-after(//text, '&#xD;')" /> 
<xsl:value-of select="'}='"/> 
<xsl:value-of select="contains(substring(substring-after(//text, '&#xD;'), 1, 2), '&#xA;')" /> 

IE11打印:

前-XA:{我们想:} = FALSE /后的xD:{*免费冰淇淋*免费 啤酒*免费换行符} = FALSE

也就是说,即使MSXML看到无论是CR和LF源XML,应用substring-before/substring-after由此产生的子字符串也不会包含,尽管它应该尽我所知。

那么,这是怎么回事?我错过了什么?关于substring- *函数? MSXML是否不一致?

回答

1

它看起来像这里发生了什么是IE浏览器进行在线处理的不只是输入的XML也是对XSLT的XML结束。刚刚尝试在IE(与任何输入XML)执行此:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
       xmlns:msxsl="urn:schemas-microsoft-com:xslt" 
       xmlns:fn="fn" 
       exclude-result-prefixes="fn msxsl"> 
    <xsl:output method="xml" indent="yes"/> 

    <msxsl:script implements-prefix="fn"> 
    function charCodes(str) { 
    var result = ''; 
    for(var i = 0; i &lt; str.length; i += 1) { 
    result += str.charCodeAt(i) + " "; 
    } 
    return result; 
    } 
    </msxsl:script> 

    <xsl:template match="/"> 
    <html> 
     <body> 
     <xsl:if test="function-available('fn:charCodes')"> 
      <div> 
      <xsl:text>Char code for xA: </xsl:text> 
      <xsl:value-of select="fn:charCodes('&#xA;')"/> 
      </div> 
      <div> 
      <xsl:text>Char code for xD: </xsl:text> 
      <xsl:value-of select="fn:charCodes('&#xD;')"/> 
      </div> 
      <div> 
      <xsl:text>Char code for xDxA: </xsl:text> 
      <xsl:value-of select="fn:charCodes('&#xD;&#xA;')"/> 
      </div> 
     </xsl:if> 
     <div> 
      <xsl:text>String length of xDxA: </xsl:text> 
      <xsl:value-of select="string-length('&#xD;&#xA;')"/> 
     </div> 
     </body> 
    </html> 
    </xsl:template> 
</xsl:stylesheet> 

这将产生在IE 10的结果,当我尝试它是:

Char code for xA: 10 
Char code for xD: 10 
Char codes for xDxA: 10 
String length of xDxA: 1 

因此,所有xDxA S和xD s的被取代与xA,我认为这完全解释你所见证的行为。

顺便说一下,在Firefox中执行相同的脚本生成:

String length of xDxA: 2 

这说明你在Firefox中看到了什么。

最后要注意的是,我可以在IE中重现上述行为,但不能在Visual Studio的XSLT功能中重现上述行为,所以似乎在MSXSL的某些实现中存在此行为,但不是全部。

+0

将数字字符引用写入时,将xA和xD字符标准化当然是不正确的,如果你是对的,那就是发生了什么。 –

+0

所以。难道我在正确理解这个当我写' '或' '在我的XSL文件时,MSXML/XSLT引擎*实际上并没有看到* CR或CR + LF,但永远只能LF字符(0x0A)?这是好的,因为它只能在输入XML中看到LF? –

+0

@MartinBa是的,这将是我对情况的理解,尽管我会建议坚持在您的XSLT中使用' ',并且希望能够为您提供跨处理器的一致行为。 – JLRishe