XSLT выбирает только узлы с текстом в цикле - PullRequest
4 голосов
/ 13 января 2011

Я хотел бы выбрать только узлы, содержащие текстовые узлы. Но когда я проверяю для 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>

OUTPUT

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 ]

3 голосов
/ 13 января 2011

У вас возникла проблема с пустыми текстовыми узлами ...

Решение, сохраняющее пробелы только для текстовых узлов (лучше при обработке (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 />
2 голосов
/ 13 января 2011

Эта проблема вызвана тем, что учитываются также текстовые узлы только для пробелов.

Решение :

Включить этот глобальный (Лучшее место - перед любой директивой <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>
2 голосов
/ 13 января 2011

Хороший вопрос.Я потратил несколько дней на поиски ответа.

<xsl:value-of select="string-length(normalize-space(text()[1]))" />
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...