Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > XML > XSLT to create filtered subset

Reply
Thread Tools

XSLT to create filtered subset

 
 
John Bailo
Guest
Posts: n/a
 
      06-12-2006

Given this XML:

<?xml version="1.0" encoding="UTF-8"?>
<pallet>
<position row="0" bay="0" level="A">
<client id="ABC"></client>
</position>
<position row="1" bay="1" level="B">
<client id="DEF"></client>
</position>
<position row="1" bay="1" level="C">
<client id="GHI"></client>
</position>
</pallet>

I want to return a subset,

<pallet>
<position row="0" bay="0" level="A">
<client id="ABC"></client>
</position>
</pallet>


But I can't seem to extend my stylesheet to something 3 nodes deep.

This:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlnssl="http://www.w3.org/1999/XSL/Transform">
<xslutput method="xml"/>
<xsl:template match="/">
<pallet>
<xsl:apply-templates select="pallet/position"/>
</pallet>
</xsl:template>
<xsl:template match="pallet">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="position[@row=0]">
<position>
<xsl:attribute name="row">
<xsl:value-of select="@row"/>
</xsl:attribute>
<xsl:attribute name="bay">
<xsl:value-of select="@bay"/>
</xsl:attribute>
<xsl:attribute name="level">
<xsl:value-of select="@level"/>
</xsl:attribute>
</position>
<xsl:apply-templates/>
</xsl:template>
</xsl:stylesheet>

will return

<?xml version="1.0" encoding="UTF-16"?>
<pallet>
<position row="0" bay="0" level="A" />
</pallet>


But say I want to extend it to return:

<?xml version="1.0" encoding="UTF-16"?>
<pallet>
<position row="0" bay="0" level="A" />
<client id="ABC">
</client>
</pallet>

How do I do that?

 
Reply With Quote
 
 
 
 
Joe Kesselman
Guest
Posts: n/a
 
      06-12-2006
John Bailo wrote:
>
> Given this XML:
>
> <?xml version="1.0" encoding="UTF-8"?>
> <pallet>
> <position row="0" bay="0" level="A">
> <client id="ABC"></client>
> </position>
> <position row="1" bay="1" level="B">
> <client id="DEF"></client>
> </position>
> <position row="1" bay="1" level="C">
> <client id="GHI"></client>
> </position>
> </pallet>
>
> I want to return a subset,
>
> <pallet>
> <position row="0" bay="0" level="A">
> <client id="ABC"></client>
> </position>
> </pallet>
>
>
> But I can't seem to extend my stylesheet to something 3 nodes deep.
>
> This:
>
> <?xml version="1.0" encoding="UTF-8"?>
> <xsl:stylesheet version="1.0"
> xmlnssl="http://www.w3.org/1999/XSL/Transform">
> <xslutput method="xml"/>
> <xsl:template match="/">
> <pallet>
> <xsl:apply-templates select="pallet/position"/>
> </pallet>
> </xsl:template>
> <xsl:template match="pallet">
> <xsl:apply-templates/>
> </xsl:template>
> <xsl:template match="position[@row=0]">
> <position>
> <xsl:attribute name="row">
> <xsl:value-of select="@row"/>
> </xsl:attribute>
> <xsl:attribute name="bay">
> <xsl:value-of select="@bay"/>
> </xsl:attribute>
> <xsl:attribute name="level">
> <xsl:value-of select="@level"/>
> </xsl:attribute>
> </position>
> <xsl:apply-templates/>
> </xsl:template>
> </xsl:stylesheet>
>
> will return
>
> <?xml version="1.0" encoding="UTF-16"?>
> <pallet>
> <position row="0" bay="0" level="A" />
> </pallet>
>
>
> But say I want to extend it to return:
>
> <?xml version="1.0" encoding="UTF-16"?>
> <pallet>
> <position row="0" bay="0" level="A" />
> <client id="ABC">
> </client>
> </pallet>
>
> How do I do that?
>



--
() ASCII Ribbon Campaign | Joe Kesselman
/\ Stamp out HTML e-mail! | System architexture and kinetic poetry
 
Reply With Quote
 
 
 
 
Joe Kesselman
Guest
Posts: n/a
 
      06-12-2006
The complicating factor here is that you want to pull <client> out of
<position>. That means you need to independently match on "the client
which is within the position with row='0'".

Maintaining your somewhat verbose style:

<xsl:template match="client[../position[@row='0']"
<client>
<xsl:attribute name="id">
<xsl:value-of select="@id"/>
</xsl:attribute>
<!-- possible apply-templates here? -->
</client>
</xsl:template/>

If you haven't already done so, you really want to look at the xsl:copy
and xsl:copy-of directives, and at the standard "identity transformation
with exceptions" approachh; those techniques would make this partcular
example significantly cleaner, unless you have a Good Reason for doing
everything explicitly.


--
() ASCII Ribbon Campaign | Joe Kesselman
/\ Stamp out HTML e-mail! | System architexture and kinetic poetry
 
Reply With Quote
 
Joe Kesselman
Guest
Posts: n/a
 
      06-12-2006
Sorry, forgot to say that you also need to modify:

<xsl:template match="pallet">
<xsl:apply-templates select="position"/>
<xsl:apply-templates select="position/client"/>
</xsl:template>

Actually, performance would probably be better if you changed that to

<xsl:template match="pallet">
<xsl:apply-templates select="position[@row=0]"/>
<xsl:apply-templates select="position[@row=0]/client"/>
</xsl:template>

You could then consider removing the predicates from the templates for
position and client.


--
() ASCII Ribbon Campaign | Joe Kesselman
/\ Stamp out HTML e-mail! | System architexture and kinetic poetry
 
Reply With Quote
 
John Bailo
Guest
Posts: n/a
 
      06-12-2006
Joe Kesselman wrote:

> You could then consider removing the predicates from the templates for
> position and client.


I am still having trouble. I changed the xslt to this. I think it
should produce an exact replica of the original XML:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlnssl="http://www.w3.org/1999/XSL/Transform">
<xslutput method="xml"/>

<xsl:template match="/">
<pallet>
<xsl:apply-templates select="pallet/position"/>
</pallet>
</xsl:template>

<xsl:template match="pallet">
<!-- BEGIN YOUR CHANGE -->
<xsl:apply-templates select="position"/>
<xsl:apply-templates select="position/client"/>
<!-- END YOUR CHANGE -->
<xsl:apply-templates/>
</xsl:template>

<xsl:template match="position">
<position>
<xsl:attribute name="row">
<xsl:value-of select="@row"/>
</xsl:attribute>
<xsl:attribute name="bay">
<xsl:value-of select="@bay"/>
</xsl:attribute>
<xsl:attribute name="level">
<xsl:value-of select="@level"/>
</xsl:attribute>
</position>
<xsl:apply-templates/>
</xsl:template>

<!-- BEGIN YOUR CHANGE -->
<xsl:template match="client[../position]">
<client>
<xsl:attribute name="id">
<xsl:value-of select="@id"/>
</xsl:attribute>
<!-- possible apply-templates here? -->
</client>
</xsl:template>
<!-- END YOUR CHANGE -->

</xsl:stylesheet>


And the result is:

<?xml version="1.0" encoding="UTF-16"?>
<pallet>
<position row="0" bay="0" level="A" />
<position row="1" bay="1" level="B" />
<position row="1" bay="1" level="C" />
</pallet>


Instead of

<?xml version="1.0" encoding="UTF-8"?>
<pallet>
<position row="0" bay="0" level="A">
<client id="ABC"></client>
</position>
<position row="1" bay="1" level="B">
<client id="DEF"></client>
</position>
<position row="1" bay="1" level="C">
<client id="GHI"></client>
</position>
</pallet>

 
Reply With Quote
 
John Bailo
Guest
Posts: n/a
 
      06-12-2006
Ok, I think I got it -- thanks for all your help!
You're second suggestion gave me the clues.

I also will try your optimizations -- you've opened my eyes as far as
the potential elegance of this language.


Here's my stylesheet:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlnssl="http://www.w3.org/1999/XSL/Transform">
<xslutput method="xml"/>

<xsl:template match="/">
<pallet>
<xsl:apply-templates select="pallet/position"/>
</pallet>
</xsl:template>

<xsl:template match="pallet">
<xsl:apply-templates select="position"/>
<xsl:apply-templates select="position/client"/>

</xsl:template>

<xsl:template match="position">
<position>
<xsl:attribute name="row">
<xsl:value-of select="@row"/>
</xsl:attribute>
<xsl:attribute name="bay">
<xsl:value-of select="@bay"/>
</xsl:attribute>
<xsl:attribute name="level">
<xsl:value-of select="@level"/>
</xsl:attribute>
<xsl:apply-templates select="client"/>
</position>

</xsl:template>


<xsl:template match="client">
<client>
<xsl:attribute name="id">
<xsl:value-of select="@id"/>
</xsl:attribute>
<!-- possible apply-templates here? -->
</client>

</xsl:template>



</xsl:stylesheet>



John Bailo wrote:
> Joe Kesselman wrote:
>
>> You could then consider removing the predicates from the templates for
>> position and client.

>
>
> I am still having trouble. I changed the xslt to this. I think it
> should produce an exact replica of the original XML:
>
> <?xml version="1.0" encoding="UTF-8"?>
> <xsl:stylesheet version="1.0"
> xmlnssl="http://www.w3.org/1999/XSL/Transform">
> <xslutput method="xml"/>
>
> <xsl:template match="/">
> <pallet>
> <xsl:apply-templates select="pallet/position"/>
> </pallet>
> </xsl:template>
>
> <xsl:template match="pallet">
> <!-- BEGIN YOUR CHANGE -->
> <xsl:apply-templates select="position"/>
> <xsl:apply-templates select="position/client"/>
> <!-- END YOUR CHANGE -->
> <xsl:apply-templates/>
> </xsl:template>
>
> <xsl:template match="position">
> <position>
> <xsl:attribute name="row">
> <xsl:value-of select="@row"/>
> </xsl:attribute>
> <xsl:attribute name="bay">
> <xsl:value-of select="@bay"/>
> </xsl:attribute>
> <xsl:attribute name="level">
> <xsl:value-of select="@level"/>
> </xsl:attribute>
> </position>
> <xsl:apply-templates/>
> </xsl:template>
>
> <!-- BEGIN YOUR CHANGE -->
> <xsl:template match="client[../position]">
> <client>
> <xsl:attribute name="id">
> <xsl:value-of select="@id"/>
> </xsl:attribute>
> <!-- possible apply-templates here? -->
> </client>
> </xsl:template>
> <!-- END YOUR CHANGE -->
>
> </xsl:stylesheet>
>
>
> And the result is:
>
> <?xml version="1.0" encoding="UTF-16"?>
> <pallet>
> <position row="0" bay="0" level="A" />
> <position row="1" bay="1" level="B" />
> <position row="1" bay="1" level="C" />
> </pallet>
>
>
> Instead of
>
> <?xml version="1.0" encoding="UTF-8"?>
> <pallet>
> <position row="0" bay="0" level="A">
> <client id="ABC"></client>
> </position>
> <position row="1" bay="1" level="B">
> <client id="DEF"></client>
> </position>
> <position row="1" bay="1" level="C">
> <client id="GHI"></client>
> </position>
> </pallet>
>

 
Reply With Quote
 
Joe Kesselman
Guest
Posts: n/a
 
      06-12-2006
John Bailo wrote:

Actually, let's make that cleaner in several ways

> <xsl:template match="pallet">

<xsl:for-each select="position[@row='0']">
<xsl:apply-templates select="."/>
<xsl:apply-templates select="client"/>
</xsl:for-each>
> </xsl:template>

....
> <xsl:template match="position">

....
> <xsl:template match="client">


Let pallet handle selecting which descendents you care about, then just
provide templates for how to render them once selected.


--
() ASCII Ribbon Campaign | Joe Kesselman
/\ Stamp out HTML e-mail! | System architexture and kinetic poetry
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
how do i create subset and union in XPath Query IMS.Rushikesh@gmail.com XML 3 10-28-2005 05:49 AM
How to avoid filtered status report - PIX. AM Cisco 1 06-21-2005 02:03 AM
ASP / VB - Save Word file to "filtered" HTML COMantilles ASP .Net 0 09-13-2003 10:41 PM
Re: Dataview filter remains filtered across users. vMike ASP .Net 1 08-26-2003 01:23 PM
Dataview filter remains filtered across users. vMike ASP .Net 1 08-26-2003 05:02 AM



Advertisments