Как отфильтровать данные по атрибуту с помощью XSLT? - PullRequest
3 голосов
/ 09 сентября 2011

Как получить только те узлы, которые имеют имя , которые начинаются с "тега" и заканчиваются на "DescRes"? Я использую XMLDataSource и GridView (ASP.NET 3.5) для отображения XML. Ничего фантастического. Если значения должны быть жестко запрограммированы в XSLT, это тоже хорошо.

<data name="tagoneCtrlNumberRes.Text" xml:space="preserve">
   <value>1.</value>
   <comment>A01</comment>
</data>
<data name="tagoneCtrlDescRes.Text" xml:space="preserve">
   <value>Hello</value>
   <comment>A01</comment>
</data>
<data name="tagoneCtrlNoteRes.Text" xml:space="preserve">
   <value>Hi</value>
   <comment>A01</comment>
</data>

Если я начну с этого XML, я бы хотел, чтобы результирующий XML после применения XSLT показывал:

<data name="tagoneCtrlDescRes.Text" xml:space="preserve">
   <value>Hello</value>
   <comment>A01</comment>
</data>

Вот мой XSLT:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">

    <xsl:param name="sortby"></xsl:param>
    <xsl:param name="orderas"></xsl:param>

    <xsl:output method="xml" indent="yes"/>

    <!--<xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>-->
    <xsl:template match="root">
        <root>
            <xsl:apply-templates select="data">
                <xsl:sort select="*[name()=$sortby]|@*[name()=$sortby]" data-type="text" order="{$orderas}"/>
            </xsl:apply-templates>
        </root>
    </xsl:template>
    <xsl:template match="data">
        <data>
            <xsl:attribute name="comment">
                <xsl:value-of select="comment" />
            </xsl:attribute>
            <xsl:attribute name="ctrlname">
                <xsl:value-of select="@name"/>
            </xsl:attribute>
            <xsl:attribute name="value">
                <xsl:value-of select="value" />
            </xsl:attribute>            
        </data>
    </xsl:template>
</xsl:stylesheet>

1 Ответ

7 голосов
/ 09 сентября 2011

В XSLT 2.0 используются стандартные функции XPath starts-with() и ends-with().

InВ Xpath 1.0 нет функции ends-with(), поэтому вам нужно использовать эквивалентное выражение XPath 1.0.

I.Решение XPath 1.0 / XSLT 1.0 :

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

 <xsl:template match="/">
     <xsl:copy-of select=
     "*/data[@name[starts-with(.,'tag')
               and
                 substring(., string-length(.)-11) = 'DescRes.Text'
                 ]
        ]
     "/>
 </xsl:template>
</xsl:stylesheet>

при применении к предоставленному фрагменту XML (создал правильно сформированный документ XML, поместив его в один верхний элемент):

<t>
    <data name="tagoneCtrlNumberRes.Text" xml:space="preserve">
        <value>1.</value>
        <comment>A01</comment>
    </data>
    <data name="tagoneCtrlDescRes.Text" xml:space="preserve">
        <value>Hello</value>
        <comment>A01</comment>
    </data>
    <data name="tagoneCtrlNoteRes.Text" xml:space="preserve">
        <value>Hi</value>
        <comment>A01</comment>
    </data>
</t>

дает требуемый, правильный результат :

<data name="tagoneCtrlDescRes.Text" xml:space="preserve">
        <value>Hello</value>
        <comment>A01</comment>
    </data>

Объяснение : XPath 1.0 эквивалент ends-with($s, $end):

substring($s, string-length($s) - string-length($end) +1) = $end

II.Решение XPath 2.0 / XSLT 2.0 :

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="/">
     <xsl:sequence select=
     "*/data[@name[starts-with(.,'tag')
               and
                 ends-with(.,'DescRes.Text')
                 ]
        ]
     "/>
 </xsl:template>
</xsl:stylesheet>

Здесь мы используем стандартную функцию Xpath 2.0 ends-with()

...