RE: [xsl] Very Basic Generic Filtering Question

Subject: RE: [xsl] Very Basic Generic Filtering Question
From: "M. David Peterson" <m.david@xxxxxxxxxx>
Date: Thu, 10 Jun 2004 19:28:35 -0600
Hey Josh,

You know, you're right, using a variable in a match pattern is an error.
Its an error that Xalan doesn?t care about and as such is something I
will use from time to time (when Xalan is the transformation engine) to
solve a problem that should be fixed by changing the XML but as a
consultant you don?t always have that luxury.

For example, this...

<?xml version="1.0"?>
<foo>
  <a length="1"/>
  <b/>
  <c/>
</foo>

processed by this... 

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
version="1.0">
<xsl:variable name="foo" select="'length'"/>
<xsl:output method="text"/>
<xsl:template match="/">
  <xsl:apply-templates select="foo/*"/>
</xsl:template>
<xsl:template match="a[@*[local-name() = $foo]]">
  Hello World
</xsl:template>
</xsl:stylesheet>

Outputs this when transformed by Xalan...

Hello World

And this when transformed by Saxon...

E The match pattern in xsl:template may not contain references to
variables	priority.xslt
file:/E:/Documents%20and%20Settings/M.David%20/My%20Documents/sample%20x
slt/priority.xslt	8:1

And this when transformed by .NET XslTransform()

Exception Details: System.Xml.XPath.XPathException: a[@*[local-name() =
$foo]] is an invalid key pattern. It either has a variable reference or
key function.


Actually the error that I think you caught Josh was the fact that there
was white space between the $ and the first character of the variable
name.  So not only am I teaching bad habits but I'm teaching them wrong
as well!  Sorry about that Arvind!  I hope I didn?t make things worse
for you!

For anybody else reading this thread the above will fail in every other
processor (that I know of) that isn?t Xalan.  So if you choose to use
the above be forewarned that it is a Xalan only solution AND it?s a
hack.

Thanks for catching this one Josh!

Best regards,

<M:D/>



-----Original Message-----
From: Josh Canfield [mailto:Josh.Canfield@xxxxxxxxxxxx] 
Sent: Thursday, June 10, 2004 6:05 PM
To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
Subject: RE: [xsl] Very Basic Generic Filtering Question

You can't put a variable in a template element's match attribute:

Error in expression $filterElement: Unexpected token in pattern, found $
javax.xml.transform.TransformerConfigurationException: Failed to compile
stylesheet. 1 error detected.


This item in Dave Pawson's FAQ might help
http://www.dpawson.co.uk/xsl/sect2/N7654.html#d9129e607

Josh

-----Original Message-----
From: M. David Peterson [mailto:m.david@xxxxxxxxxx]
Sent: Thursday, June 10, 2004 4:54 PM
To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
Subject: RE: [xsl] Very Basic Generic Filtering Question


Hey Arvind,

You're on the right track.  Whenever you have an element that you want
to do absolutely nothing with (and is a direct child element of the
current Result Tree Fragment returned by your XPath, and therefore will
be looking for somewhere to go so to speak...) all you need to do is
create an empty template that matches the element name.... In this case
your second template with the match attribute set to "Header".  The way
you would implement the same thing with your filter param would be to
set the match attribute value as such...

<xsl:template match="*[not(local-name() = $ filterElement)]">
	...
</xsl:template>

The one thing that is wrong with the below stylesheet is that you are
currently running apply-templates without the select attribute and so by
default it is matching all the child elements of "/" which is referred
to as the root element... Which technically isn't an element that you or
I ever see...  but there's no need to cloud the water with why that
is...  In this case the only child element of root is AddressBook.  In
the template I assume you are matching it to you are then making a copy
of the current element (AddressBook) which contains all of its children
and there children etc...  Which of course contains the Header element
you are trying to filter out.  

Two ways to solve this problem...

First, change the <xsl:apply-templates/> to <xsl:apply-templates
select="AddressBook/*"/> to process all the children of AddressBook

OR

Add an <xsl:apply-templates/> to the template that AddressBook matches
to as to ensure that all the children of AddressBook are recursively
processed.  Unless there is something specific you want to output for
the element AddressBook then I would use the first method as it will
save you a template or two of code, one less element to match to a
template, and ultimately a faster transformation of your XML.

Hope this helps! 

Best regards,

<M:D/>



-----Original Message-----
From: Arvind Bassi [mailto:arvind_bassi@xxxxxxxxxxx] 
Sent: Thursday, June 10, 2004 4:06 PM
To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
Subject: [xsl] Very Basic Generic Filtering Question

I haven't done XSLT for quite some time, and its amazing how much l
have forgotten.

I have a very simple problem of having to filter out a specific xml
element. In the example below, it is <Header>, but it should be able to
be passed down as a parameter. From memory, l need to use the name
function and test it against the current node, but l have tried doing
this but to no avail.

How can the following xml document be filtered in a generic manner?


<?xml version="1.0" encoding="UTF-8"?>
<AddressBook>
    <Header>
        <ElementOne id="1">hello</ElementOne>
        <ElementTwo id="2"> why not</ElementTwo>
    </Header>
    <People value="3">
        <Name number="3">
            <FirstName> Simon</FirstName>
            <LastName>Says</LastName>
        </Name>
        <Name number="3">
            <FirstName> Simon</FirstName>
            <LastName>Says</LastName>
        </Name>
        <Name number="3">
            <FirstName> Simon</FirstName>
            <LastName>Says</LastName>
        </Name>
        <Name number="3">
            <FirstName> Simon</FirstName>
            <LastName>Says</LastName>
        </Name>
    </People>
    <Mary>
        <Had a="little"> lamb</Had>
    </Mary>
</AddressBook>


<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.1"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
    <xsl:output indent="yes" method="xml" version="1.0"/>
    <xsl:param name="filterElement">Header</xsl:param>
    <xsl:template match="/">
        <xsl:copy>
            <xsl:apply-templates/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="???????">
        <xsl:copy-of select="."/>
    </xsl:template>
    <xsl:template match="????????"/>
</xsl:stylesheet>

Any help that can be provided would be gratefully appreciated.

Thanks.

Arvind.





	
	
		
___________________________________________________________ALL-NEW
Yahoo! Messenger - sooooo many all-new ways to express yourself
http://uk.messenger.yahoo.com

--+------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe@xxxxxxxxxxxxxxxxxxxxxx>
--+--


--+------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe@xxxxxxxxxxxxxxxxxxxxxx>
--+--


--+------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe@xxxxxxxxxxxxxxxxxxxxxx>
--+--


Current Thread