3

How do I only pull nodes that have name that begin with "tag" and end with "DescRes"? I am using a XMLDataSource and GridView (ASP.NET 3.5) to display the XML. Nothing fancy. If values need to be hard-coded in the XSLT, that's fine too.

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

If I start with this XML, I'd like the resultant XML after the XSLT is applied to show:

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

Here is my 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
  • Good question, +1. See my answer for a one-line XPath 1.0 expression - solution and its complete XSLT 1.0 - based verification. Detailed explanation is provided. Commented Sep 9, 2011 at 15:56

1 Answer 1

7

In XSLT 2.0 use the standard XPath functions starts-with() and ends-with().

In Xpath 1.0 there isn't a function ends-with() so you need to use an equivalent XPath 1.0 expression.

I. XPath 1.0 / XSLT 1.0 solution:

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

when applied on the provided XML fragment (made a well-formed XML document by wrapping it into a single top element):

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

produces the wanted, correct result:

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

Explanation: The XPath 1.0 equivalent of ends-with($s, $end) is this:

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

II. XPath 2.0 /XSLT 2.0 solution:

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

Here we use the Xpath 2.0 standard function ends-with()

Sign up to request clarification or add additional context in comments.

3 Comments

Only one question. Does it have to be in that exact format? I was hoping to adapt it to what I already have. Right now, I have the attributes mapped in my XSLT to my GridView.
@dotnetN00b: No solution is absolute and most solutions at SO while solving a problem in a specific way, can be re-used/adapted in/to a class of similar problems. In this particular case, you can re-use the gained knowledge in any scenario asking for ends-with(). Of course, you need to have at least a basic knowledge of XPath and this is true for any programming language you are given a solution in.
Fair enough. At least, I have a base to work from. Thanks, Dimitre.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.