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] |