[XSL樣式表]xPath學習

 

 

test1.xml:

<?xml version="1.0" encoding="utf-8"?>
<?xml:stylesheet type="text/xsl" href="test3.xsl"?>
<root>
    <e1>
        <e1-1>
            <e1-1-1>
                1231.23
            </e1-1-1>
        </e1-1>
        <e1-2>
            4564.56
        </e1-2>
    </e1>
    <e2>
        <e2-1>
            789.789
        </e2-1>
        <e2-2>
            <e2-2-1>
                0120.12
            </e2-2-1>
        </e2-2>
        <e2-3>
            3453.45
        </e2-3>
    </e2>
    <e3>
        <e3-1>
            <e3-1-1>
                6.78678
            </e3-1-1>
            <e3-1-2>
                <e3-1-2-1>
                    9019.01
                </e3-1-2-1>
            </e3-1-2>
        </e3-1>
        <e3-2>
            <e3-2-1>
                234.234
            </e3-2-1>
        </e3-2>
    </e3>
</root>

 

test1.xsl:

 

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
    <xsl:template match="/">
        <html><body>
        <xsl:apply-templates select="root/e2"/>
        </body></html>
    </xsl:template>
    <xsl:template name="temp1" match="root/e2">
        [preceding::root/e2/]
        <xsl:for-each select="preceding::node()">
            [<xsl:value-of select="local-name()"/>]
        </xsl:for-each>
        <hr/>
        [following::root/e2/]
        <xsl:for-each select="following::node()">
            [<xsl:value-of select="local-name()"/>]
        </xsl:for-each>
        <hr/>
        [preceding-sibling::root/e2/]
        <xsl:for-each select="preceding-sibling::node()">
            [<xsl:value-of select="local-name()"/>]
        </xsl:for-each>
        <hr/>
        [following-sibling::root/e2/]
        <xsl:for-each select="following-sibling::node()">
            [<xsl:value-of select="local-name()"/>]
        </xsl:for-each>
        <hr/>
        [descendant::root/e2/]
        <xsl:for-each select="descendant::node()">
            [<xsl:value-of select="local-name()"/>]
        </xsl:for-each>
        <hr/>
        [ancestor::root/e2/]
        <xsl:for-each select="ancestor::node()">
            [<xsl:value-of select="local-name()"/>]
        </xsl:for-each>
        <hr/>
        [descendant-or-self::root/e2/]
        <xsl:for-each select="descendant-or-self::node()">
            [<xsl:value-of select="local-name()"/>]
        </xsl:for-each>
        <hr/>
        [ancestor-or-self:root/e2/]
        <xsl:for-each select="ancestor-or-self::node()">
            [<xsl:value-of select="local-name()"/>]
        </xsl:for-each>
        <hr/>
        [parent::root/e2/]
        <xsl:for-each select="parent::node()">
            [<xsl:value-of select="local-name()"/>]
        </xsl:for-each>
        <hr/>
        [child::root/e2/]
        <xsl:for-each select="child::node()">
            [<xsl:value-of select="local-name()"/>]
        </xsl:for-each>
        <hr/>
        [self::root/e2/]
        [<xsl:value-of select="local-name(self::node())"/>]
        <hr/>
    </xsl:template>
</xsl:stylesheet>

 

結果:下圖中的[]代表textNode()。因爲node()方法包含所有類型的節點。因此使用該方法時應該留意對類型進行過濾。

 

[preceding::root/e2/] [xml:stylesheet] [e1] [e1-1] [e1-1-1] [] [e1-2] [] [following::root/e2/] [e3] [e3-1] [e3-1-1] [] [e3-1-2] [e3-1-2-1] [] [e3-2] [e3-2-1] [] [preceding-sibling::root/e2/] [e1] [following-sibling::root/e2/] [e3] [descendant::root/e2/] [e2-1] [] [e2-2] [e2-2-1] [] [e2-3] [] [ancestor::root/e2/] [] [root] [descendant-or-self::root/e2/] [e2] [e2-1] [] [e2-2] [e2-2-1] [] [e2-3] [] [ancestor-or-self:root/e2/] [] [root] [e2] [parent::root/e2/] [root] [child::root/e2/] [e2-1] [e2-2] [e2-3] [self::root/e2/] [e2]

 

test2.xsl:

 

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
    <xsl:template match="/">
        <html><body>
        <xsl:apply-templates select="root/e2"/>
        </body></html>
    </xsl:template>
    <xsl:template match="root/e2">
        [root/e2/e2-1][ceiling(
        <xsl:value-of select="child::node()[local-name()='e2-1']"/>
        )=<xsl:value-of select="ceiling(child::node()[local-name()='e2-1'])"/>]
        <hr/>
        [root/e2/e2-2/e2-2-1][floor(
        <xsl:value-of select="descendant::node()[local-name()='e2-2-1']"/>
        )=<xsl:value-of select="floor(descendant::node()[local-name()='e2-2-1'])"/>]
        <hr/>
        [root/e1/e1-1-1 + root/e3/e3-1-1][
        <xsl:value-of select="preceding::node()[local-name()='e1-1-1']"/>
        +
        <xsl:value-of select="following::node()[local-name()='e3-1-1']"/>
        =
        <xsl:value-of select="preceding::node()[local-name()='e1-1-1'] + following::node()[local-name()='e3-1-1']"/>]
        <hr/>
        [root/e2/e2-2/e2-2-1][round(
        <xsl:value-of select="descendant::node()[local-name()='e2-2-1']"/>
        )=
        <xsl:value-of select="round(descendant::node()[local-name()='e2-2-1'])"/>]
        <hr/>
        [root/e2 counts of descendants]
        [count(nodes)=
        <xsl:value-of select="count(descendant::node())"/>]
        [count(elements)=
        <xsl:value-of select="count(descendant::node()[boolean(local-name())])"/>]
        [count(texts)=
        <xsl:value-of select="count(descendant::node()[boolean(text())])"/>]
        <hr/>
        [root/e2][number(text())=
        <xsl:value-of select="number(self::node()/text())"/>]
        [number(boolean(text()))=
        <xsl:value-of select="number(boolean(self::node()/text()))"/>]
        [number(string(text()))=
        <xsl:value-of select="number(string(self::node()/text()))"/>]
        <hr/>
    </xsl:template>
   
</xsl:stylesheet>

 

結果:這一部分測試xPath中數值函數的運用,幾點結論:

一、當任意類型之間用+相加時,相加之前元素會先轉換爲number類型。

二、形如0120.12這樣以零開頭的字串,轉換成number型時不會報錯。

三、可以用boolean(local-name())和boolean(text())的方式過濾節點類型。

四、對於不含textNode的元素或父元素,number()並不將其轉換爲0,而是轉換爲NaN。對於這些節點,可以用number(boolean(text())的方式轉換爲。

 

[root/e2/e2-1][ceiling( 789.789 )=790] [root/e2/e2-2/e2-2-1][floor( 0120.12 )=120] [root/e1/e1-1-1 + root/e3/e3-1-1][ 1231.23 + 6.78678 = 1238.01678] [root/e2/e2-2/e2-2-1][round( 0120.12 )= 120] [root/e2 counts of descendants] [count(nodes)= 7] [count(elements)= 4] [count(texts)= 3] [root/e2][number(text())= NaN] [number(boolean(text()))= 0] [number(string(text()))= NaN]

 

test3.xsl:

 

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
    <xsl:template match="/">
        <html><body>
            <xsl:apply-templates select="root/e2"/>
        </body></html>
    </xsl:template>
    <xsl:template match="root/e2">
       
        [root/e2][starts-with(
        <xsl:value-of select="descendant::node()[local-name()='e2-2-1']"/>
        ,'01')=
        <xsl:value-of select="starts-with(descendant::node()[local-name()='e2-2-1'],'01')"/>]
        [root/e2][starts-with(normalize-space(
        <xsl:value-of select="descendant::node()[local-name()='e2-2-1']"/>)
        ,'01')=
        <xsl:value-of select="starts-with(normalize-space(descendant::node()[local-name()='e2-2-1']),'01')"/>]
        [starts-with(number(
        <xsl:value-of select="descendant::node()[local-name()='e2-2-1']"/>)
        ,'1')=
        <xsl:value-of select="starts-with(number(descendant::node()[local-name()='e2-2-1']),'1')"/>]
       
        <hr/>
        [root/e2][starts-with(
        0120.12,01)=
        <xsl:value-of select="starts-with(0120.12, 01)"/>]
        [starts-with(
        '0120.12','01')=
        <xsl:value-of select="starts-with('0120.12', '01')"/>]
        [starts-with(
        0120.12,1)=
        <xsl:value-of select="starts-with(0120.12, 1)"/>]
        [starts-with(
        0120.12,00001)=
        <xsl:value-of select="starts-with(0120.12, 00001)"/>]
        <hr/>
        [starts-with(string(
        <xsl:value-of select="child::node()[local-name()='e2-3']"/>),'345')=
        <xsl:value-of select="starts-with(string(child::node()[local-name()='e2-3']), '345')"/>]
        [starts-with(number(
        <xsl:value-of select="child::node()[local-name()='e2-3']"/>),'345')=
        <xsl:value-of select="starts-with(number(child::node()[local-name()='e2-3']), '345')"/>]
        [starts-with(
        <xsl:value-of select="local-name()"/>,'e')=
        <xsl:value-of select="starts-with(local-name(), e)"/>]
        <hr/>
       
    </xsl:template>
</xsl:stylesheet>

 

結果:這一部分測試字串函數,幾點結論:

一、在使用字串函數時,如果參數是節點或節點集要小心地處理空白,否則會產生令你嗔目結舌的結果。很多人習慣在XML文件的編輯軟件如UE等中設定將Tab轉換爲空白,應記得先調用normalize-space()函數去掉不需要的空白。

二、但字串函數的參數不是節點或節點集而需要類型轉換時,XSL是依照boolean->number->string的次序進行轉換的。

所以對於下圖中的0120.12實際上先被轉換成120.12,然後被轉換成'120.12',00001先轉換成1,然後被轉換成'1'。

三、substring()以1爲頭一個字符的索引值

四、translate()函數提供了一種高效、便捷地替換字符的方法,爲了達到預定效果,應確保該函數的第二個和第三個參數的字符長度總是相等,因爲長度不一時,較長參數的多餘字符將被自動截掉。

 

 

[root/e2][starts-with( 0120.12 ,'01')= false] [root/e2][starts-with(normalize-space( 0120.12 ) ,'01')= true] [starts-with(number( 0120.12 ) ,'1')= true]


[root/e2][starts-with( 0120.12,01)= true] [starts-with( 0120.12,'01')= false] [starts-with( 0120.12,1)= true] [starts-with( 0120.12,00001)= true]


[starts-with(string( 3453.45 ),'345')= false] [starts-with(number( 3453.45 ),'345')= true] [starts-with( e2,'e')= true]


[string-length( 789.789 )= 29] [string-length(normalize-space( 789.789 ))= 7] [contains( 789.789 , 789)= true] [substring('substring',3,4)= bstr] [substring(123456, 2,10)= 23456] [substring(123456, -2,4)= 1] [substring(123456, 5,-2)= ] [substring-after('12-34-56', '-')= 34-56] [substring-after('12-34-56', '')= 12-34-56] [substring-before('12-34-56', '-')= 12] [substring-before('12-34-56', '')= ] [translate('12a34b56c', 'abc', 'xyz')= 12x34y56z] [translate('12a34b56c', 'abcdefg', 'xyz')= 12x34y56z] [translate('12a34b56c', 'abc', 'xyzlmn')= 12x34y56z] [translate('12a34b56c78a90b12c', 'abc', 'xyz')= 12x34y56z78x90y12z]

 

 

發佈了75 篇原創文章 · 獲贊 3 · 訪問量 23萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章