2014-03-05 55 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