XSLT仅选择循环中带文本的节点

时间:2011-01-13 16:31:01

标签: xslt xpath

我想只选择包含文本节点的节点。但是,当我测试text()时,包含带有文本的子节点的父节点也会被返回。我试着检查一下 string-length()但父节点返回的字符串长度大于0。

在这种情况下,我只想选择

SendDate
FirstName
LastName
Company
Street
City
State
Zip

由于

XML

<BusinessLetter>
    <Head>
        <SendDate>November 29, 2005</SendDate>
        <Recipient>
            <Name Title="Mr.">
                <FirstName>Joshua</FirstName>
                <LastName>Lockwood</LastName>
            </Name>
            <Company>Lockwood &amp; Lockwood</Company>
            <Address>
                <Street>291 Broadway Ave.</Street>
                <City>New York</City>
                <State>NY</State>
                <Zip>10007</Zip>
                <Country>United States</Country>
            </Address>
        </Recipient>
    </Head>
</BusinessLetter>

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" indent="yes"/>
    <xsl:template match="/">
        <xsl:for-each select="//*[text()]">
            <xsl:if test="text()">
                    <Match>
                        <xsl:value-of select="name()"/>:
                        <xsl:value-of select="string-length(text())"/>
                    </Match>
                    <br />
            </xsl:if>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

输出

BusinessLetter: 2
Head: 3
SendDate: 17
Recipient: 4
Name: 5
FirstName:6
LastName:8
Company:19
Address:5
Street:17
City:8
State:2
Zip:5
Country:13

3 个答案:

答案 0 :(得分:3)

您遇到仅限空白文本节点的问题...

解决方案仅保留空白区域文本节点(处理(X)HTML时更好):

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="*[text()[normalize-space()]]">
        <Match>
            <xsl:value-of select="concat(name(),
                                         ' : ',
                                         string-length(normalize-space()))"/>
        </Match>
        <br />
    </xsl:template>
</xsl:stylesheet>

输出:

<Match>SendDate : 17</Match>
<br />
<Match>FirstName : 6</Match>
<br />
<Match>LastName : 8</Match>
<br />
<Match>Company : 19</Match>
<br />
<Match>Street : 17</Match>
<br />
<Match>City : 8</Match>
<br />
<Match>State : 2</Match>
<br />
<Match>Zip : 5</Match>
<br />
<Match>Country : 13</Match>
<br />

答案 1 :(得分:2)

好问题。我花了几天时间寻找答案。

<xsl:value-of select="string-length(normalize-space(text()[1]))" />

答案 2 :(得分:2)

此问题是由仅考虑仅限空格的文本节点引起的。

<强>解决方案

包含此全局(最佳位置在任何<xsl:template>)指令之前

<xsl:strip-space elements="*"/>

这指示XSLT处理器剥离XML文档中任何(*)元素的仅限空格的文本节点子节点。

所以,您的固定转化现在是

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="html" indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="/">
        <xsl:for-each select="//*[text()]">
            <xsl:if test="text()">
                <Match>
                    <xsl:value-of select="name()"/>:                         
                    <xsl:value-of select="string-length(text())"/>
                </Match>
                <br />
            </xsl:if>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

并应用于提供的XML文档

<BusinessLetter>
    <Head>
        <SendDate>November 29, 2005</SendDate>
        <Recipient>
            <Name Title="Mr.">
                <FirstName>Joshua</FirstName>
                <LastName>Lockwood</LastName>
            </Name>
            <Company>Lockwood &amp; Lockwood</Company>
            <Address>
                <Street>291 Broadway Ave.</Street>
                <City>New York</City>
                <State>NY</State>
                <Zip>10007</Zip>
                <Country>United States</Country>
            </Address>
        </Recipient>
    </Head>
</BusinessLetter>

产生了想要的正确结果

<Match>SendDate:                         
                    17
</Match><br><Match>FirstName:                         
                    6
</Match><br><Match>LastName:                         
                    8
</Match><br><Match>Company:                         
                    19
</Match><br><Match>Street:                         
                    17
</Match><br><Match>City:                         
                    8
</Match><br><Match>State:                         
                    2
</Match><br><Match>Zip:                         
                    5
</Match><br><Match>Country:                         
                    13
</Match><br>