[XSL-LIST Mailing List Archive Home]
[By Thread]
[By Date]
Mark,
You write:
The part of XQuery that would do what you want is XPath, and XPath is also available in XSLT: in fact it's close to the heart of it. What you want to do is what XSLT was designed to do, so you should use it.
For example, if your XSLT currently has something like:
you could amend this simply by saying
<xsl:apply-templates select="//msDesc[*/title='AAAA']"/>
instead of the apply-templates you already have, and the selection you want would occur.
Or, if your XSLT has something like this:
you could change that xsl:apply-templates like this:
<xsl:apply-templates select="msDesc[*/title='AAAA']"/>
and do it that way.
(There is a subtle but important distinction between the two XPath expressions I just used.)
The next question you should be asking is why this works. The answer to that lies in XSLT's traversal of the source document while it builds the result. By selecting nodes in the source document to apply templates to, instead of simply applying templates to the children in the normal manner (which is what happens by default, to allow a complete tree traversal), you can effectively direct exactly which nodes in your input are processed where.
That's what we call a "pull" approach since it works by actively selecting nodes from the source. An alternative method, and one that is often preferable, is to use what we call "push". This technique allows the default traversal to occur, except it intervenes at points to affect processing by matching nodes selectively (as opposed to selecting them to apply templates to).
In your case, you might get what you want by adding something as simple as this to your stylesheet:
<xsl:template match="msDesc[not(*/title='AAAA')]" priority="2"/>
What does this do? It matches msDesc elements that have no 'title' grandchild with the value 'AAAA' and -- does nothing with them. So they do not appear in the result document (they are, effectively, dropped, leaving only the ones you want).
You could even leave the 'priority="2"' off this template if you have confidence that it will override any other templates matching "msDesc" (which it probably does, depending on a couple of rules you will also need to learn in order to master the language).
This is all really easy -- if you know how it works. If you're guessing it can be baffling. (It's fortunate this list is around.)
At 04:22 PM 7/16/2009, you wrote:
Re: [xsl] Applying an XSLT-file to specific nodes within an XML file
Subject: Re: [xsl] Applying an XSLT-file to specific nodes within an XML file From: Wendell Piez <wapiez@xxxxxxxxxxxxxxxx> Date: Thu, 16 Jul 2009 17:27:55 -0400 |
Mark,
You write:
A possible solution to this would be to write a simple XQuery script to extract the relevant <msDesc> nodes and put them in a separate XML file, which can then be transformed. That requires a lot of manual labour (especially since my titles go from AAAA to PPPP...), so I was wondering whether there is a work-around or short-cut within XSL?
The part of XQuery that would do what you want is XPath, and XPath is also available in XSLT: in fact it's close to the heart of it. What you want to do is what XSLT was designed to do, so you should use it.
For example, if your XSLT currently has something like:
<xsl:template match="/"> <html> <head>... stuff ... </head> <body> <xsl:apply-templates/> </body> </html> </xsl:template>
you could amend this simply by saying
<xsl:apply-templates select="//msDesc[*/title='AAAA']"/>
instead of the apply-templates you already have, and the selection you want would occur.
Or, if your XSLT has something like this:
<xsl:template match="mss"> <div class="mss"> <xsl:apply-templates/> </div> <xsl:template>
you could change that xsl:apply-templates like this:
<xsl:apply-templates select="msDesc[*/title='AAAA']"/>
and do it that way.
(There is a subtle but important distinction between the two XPath expressions I just used.)
The next question you should be asking is why this works. The answer to that lies in XSLT's traversal of the source document while it builds the result. By selecting nodes in the source document to apply templates to, instead of simply applying templates to the children in the normal manner (which is what happens by default, to allow a complete tree traversal), you can effectively direct exactly which nodes in your input are processed where.
That's what we call a "pull" approach since it works by actively selecting nodes from the source. An alternative method, and one that is often preferable, is to use what we call "push". This technique allows the default traversal to occur, except it intervenes at points to affect processing by matching nodes selectively (as opposed to selecting them to apply templates to).
In your case, you might get what you want by adding something as simple as this to your stylesheet:
<xsl:template match="msDesc[not(*/title='AAAA')]" priority="2"/>
What does this do? It matches msDesc elements that have no 'title' grandchild with the value 'AAAA' and -- does nothing with them. So they do not appear in the result document (they are, effectively, dropped, leaving only the ones you want).
You could even leave the 'priority="2"' off this template if you have confidence that it will override any other templates matching "msDesc" (which it probably does, depending on a couple of rules you will also need to learn in order to master the language).
This is all really easy -- if you know how it works. If you're guessing it can be baffling. (It's fortunate this list is around.)
Cheers, Wendell
At 04:22 PM 7/16/2009, you wrote:
Hi all,
Hopefully someone can assist me in solving a (probably rather basic) problem related to restricting the execution of an XSLT file to a specific part of an XML file.
My XML file looks like this (very simplified):
<mss> <msDesc> <msItem> <title>AAAA</title> </msItem> </msDesc> <msDesc> <msItem> <title>BBBB</title> </msItem> </msDesc> <msDesc> <msItem> <title>CCCC</title> </msItem> </msDesc> </mss>
I have written an XSLT file which transforms my entire XML into a nice HTML file. I would now like to restrict the XSLT file so that it ONLY transforms the <msDesc> nodes which have a <title> tag with the value 'AAAA'. So, in simpler terms, I would like to say to my XSL file:
1. Find all <msDesc> nodes which have a <title> tag with the value 'AAAA'.
2. Apply the following <xsl:template> transformations, but only to the <msDesc> nodes specified above.
3. [And then all my <xsl:template> transformations]
A possible solution to this would be to write a simple XQuery script to extract the relevant <msDesc> nodes and put them in a separate XML file, which can then be transformed. That requires a lot of manual labour (especially since my titles go from AAAA to PPPP...), so I was wondering whether there is a work-around or short-cut within XSL?
I hope this makes sense. I'm sure there's something obvious I'm missing...
Many thanks in advance, Mark
====================================================================== Wendell Piez mailto:wapiez@xxxxxxxxxxxxxxxx Mulberry Technologies, Inc. http://www.mulberrytech.com 17 West Jefferson Street Direct Phone: 301/315-9635 Suite 207 Phone: 301/315-9631 Rockville, MD 20850 Fax: 301/315-8285 ---------------------------------------------------------------------- Mulberry Technologies: A Consultancy Specializing in SGML and XML ======================================================================
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] Applying an XSLT-file to , Brandon Ibach | Thread | [xsl] Question regarding altering s, Ylvisaker, Steve |
Re: [xsl] Applying an XSLT-file to , Brandon Ibach | Date | [xsl] question on line breaks / che, Hermann Stamm-Wilbra |
Month |