[XSL-LIST Mailing List Archive Home] [By Thread] [By Date]

Re: [xsl] XSLT Filtering based on defined XML


Subject: Re: [xsl] XSLT Filtering based on defined XML
From: Jacquo Johnson <genxgeek@xxxxxxxxx>
Date: Tue, 16 Aug 2005 17:51:37 -0600

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: [xsl] 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: [xsl] 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
Keywords