How do I filter data by attribute using XSLT?
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>开发者_如何学Python;
</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>
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()
精彩评论