[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message]

Re: XSLT Filtering based on defined XML

Subject: Re: XSLT Filtering based on defined XML
From: Jacquo Johnson <genxgeek@xxxxxxxxx>
Date: Tue, 16 Aug 2005 17:51:37 -0600
xslt filtering
Yes, Indeed!  Thank you very much for the help with this one, Michael!

On 8/16/05, Michael Kay <mike@xxxxxxxxxxxx> wrote:
> OK, I' having to make a few guesses about what you want to happen to text
> nodes etc, but it seems to be something like this:
>
> Each node N of the input document has a corresponding node F in the filter
> document.
>
> The root node of the of the input document corresponds to the root node of
> the filter document.
>
> If F has no element children, then N is deep-copied unchanged to the result
> tree.
>
> If F has one or more element children, then N is shallow-copied to the
> result tree. Those children of N where a child of F exists with the same
> name are handled recursively using the same rules, using that element of F
> as the corresponding node; those children of N where no child of F exists
> with the same name are omitted from the output.
>
> OK?
>
> (There doesn't seem to be any mechanism for shallow-copying N without any
of
> its children: the rule "no children in the filter means copy all children
> from the input" seems a slighly odd one).
>
>
>
> This suggests processing something like this (2.0 solution):
>
> <xsl:variable name="in" select="/"/>
> <xsl:variable name="filter" select="doc('filter.xml')">
>
> <xsl:template match="/">
>   <xsl:apply-templates select="*">
>     <xsl:with-param name="f" select="$filter/*"/>
>   </xsl:apply-templates>
> </xsl:template>
>
> <xsl:template match="*">
>   <xsl:param name="f"/>
>   <xsl:choose>
>   <xsl:when test="$f/*">
>     <xsl:for-each select="*[node-name() = $f/*/node-name()]">
>       <xsl:apply-templates select=".">
>         <xsl:with-param name="f" select="f/*[node-name() =
> current()/node-name()]"/>
>       </xsl:apply-templates>
>     </xsl:for-each>
>   </xsl:when>
>   <xsl:otherwise>
>     <xsl:copy-of select="."/>
>   </xsl:otherwise>
>   </xsl:choose>
> </xsl:template>
>
> Untested, of course.
>
> Michael Kay
> http://www.saxonica.com/
>
> > -----Original Message-----
> > From: Jacquo Johnson [mailto:genxgeek@xxxxxxxxx]
> > Sent: 17 August 2005 00:09
> > To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> > Subject: Re:  XSLT Filtering based on defined XML
> >
> > Actually, the nice thing about the requirements in this case is that
> > the source document will always be the same structure.  That is, it is
> > well defined other than the filters, which can change but only
> > according to the xml source document definition (just the xml
> > structure...not refering to a dtd here);:
> >
> > Let's say the the following is the actual xml source contents
> > (always static):
> >
> > <Root>
> >   <Node1/>
> >   <Node2>
> >      <Node21/>
> >      <Node22/>
> >  </Node2>
> > </Root>
> >
> > Now the only available filters for this document would be:
> >
> > Filter 1:
> > <Root>
> >   <Node1/>
> > </Root>
> >
> > Output (from Filter1):
> > <Root>
> >   <Node1/>
> > </Root>
> > --
> > Filter 2:
> > <Root>
> >   <Node2>
> >      <Node21/>
> >  </Node2>
> > </Root>
> >
> > Output (from Filter2):
> > <Root>
> >   <Node2>
> >      <Node21/>
> >  </Node2>
> > </Root>
> >
> > Filter 3:
> > <Root>
> >   <Node2>
> >      <Node22/>
> >  </Node2>
> > </Root>
> >
> > Output (from Filter3):
> > <Root>
> >   <Node2>
> >      <Node22/>
> >  </Node2>
> > </Root>
> >
> > Filter 4:
> > <Root>
> >   <Node2/>
> > </Root>
> >
> > Output (from Filter2):
> > <Root>
> >   <Node2>
> >      <Node21/>
> >      <Node22/>
> >  </Node2>
> > </Root>
> >
> > Now, since I have a DOM object available I can dynamically create my
> > own xslt by recursing the filter and create <apply-templates
> > match="<CurrentNodeFromFilter>"/> and either <copy> if the node
> > doesn't have children or do a <copy-of> if the node has children.
> > Once I have the dynamic transform (as created per the filter) I can
> > call a transform with it on the xml source document to get me the
> > desired output.  This works but I think that it's kludgey.
> >
> > ----
> > On 8/16/05, Michael Kay <mike@xxxxxxxxxxxx> wrote:
> > > Your first challenge is to specify this more precisely.
> > >
> > > In early drafts of the XQuery specification there was a
> > function called
> > > filter() which was a bit like this, but it got taken out
> > because no-one was
> > > able to write a precise specification of what it was supposed to do.
> > > Sketching out an example isn't good enough. Start by
> > producing a dozen
> > > examples: For example, what output do you want if one of
> > the documents is
> > >
> > > <a><b/></a>
> > >
> > > and the other is
> > >
> > > <b><c/></b>
> > >
> > > then generalize from the examples to define the actual rules.
> > >
> > > Michael Kay
> > >
> > > > -----Original Message-----
> > > > From: Jacquo Johnson [mailto:genxgeek@xxxxxxxxx]
> > > > Sent: 16 August 2005 20:26
> > > > To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> > > > Subject:  XSLT Filtering based on defined XML
> > > >
> > > > Hi All,
> > > >
> > > > Is there an elegant pattern via xslt to filter out an
> > existing source
> > > > xml document based on the contents of another filter xml document?
> > > > For example:
> > > >
> > > > Source xml doc:
> > > > <Root>
> > > >    <Node1>
> > > >       <Node11>
> > > >         <Node111/>
> > > >       </Node11>
> > > >       <Node12/>
> > > >    <Node2>
> > > >    ...
> > > >
> > > > Filter xml doc:
> > > > <Root>
> > > >    <Node1>
> > > >      <Node111/>
> > > >    </Node1>
> > > > </Root>
> > > >
> > > > Desired results:
> > > > <Root>
> > > >    <Node1>
> > > >      <Node111/>
> > > >    </Node1>
> > > > </Root>
> > > >
> > > > Now the issue that I'm dealing with is that the filter xml doc is
> > > > dynamic.  That is, it can be different for any given xml
> > source doc
> > > > configuration based on what another server source
> > specifies.  I could
> > > > recursively build some dynamic xslt and add
> > apply-templates for each
> > > > node and make use of copy and copy-of based on if a node
> > has children
> > > > or not and then run that dynamically build transform on
> > the xml doc
> > > > source...however, can anybody think of another way to do this?
> > > >
> > > > Thanks in advance!

Current Thread

PURCHASE STYLUS STUDIO ONLINE TODAY!

Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!

Buy Stylus Studio Now

Download The World's Best XML IDE!

Accelerate XML development with our award-winning XML IDE - Download a free trial today!

Don't miss another message! Subscribe to this list today.
Email
First Name
Last Name
Company
Subscribe in XML format
RSS 2.0
Atom 0.3
Site Map | Privacy Policy | Terms of Use | Trademarks
Free Stylus Studio XML Training:
W3C Member
Stylus Studio® and DataDirect XQuery ™are products from DataDirect Technologies, is a registered trademark of Progress Software Corporation, in the U.S. and other countries. © 2004-2013 All Rights Reserved.