Newbie: Only select certain nodes in an xsl:template match

Discussion in 'XML' started by David Cater, May 28, 2007.

  1. David Cater

    David Cater Guest

    This seems like a simple task, but I'm banging my head against it.
    Something about XML/XPath just isn't clicking for me yet. Here's some
    sample XML:

    <people>
    <person name="David">
    Person 1 text
    <child age="13">Ruby</child>
    <child age="15">Rosie</child>
    </person>
    <person name="Wes">
    Person 2 text
    <child age="5">Erin</child>
    <child age="2">Rowan</child>
    </person>
    </people>

    If I want to copy everything, I can do that with this XSL:

    <xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
    <xsl:eek:utput method="xml" indent="yes" />
    <xsl:template match="*">
    <xsl:copy>
    <xsl:copy-of select="@*" />
    <xsl:apply-templates />
    </xsl:copy>
    </xsl:template>
    </xsl:stylesheet>

    What if I only want to copy the nodes where person name="David"? I'm trying
    to think about how the parser is processing this, and where some sort of
    pattern/predicate would go, and none of my experiments to try to get that to
    work are working at all.

    Thanks,

    David
    David Cater, May 28, 2007
    #1
    1. Advertising

  2. David Cater

    David Cater Guest

    Fantastic.

    So based on my understanding of XSL, what that basically says is:

    - Match everything that is an attribute or is a node.
    - In that template, copy the external tag for what was matched, and then
    apply remaining templates.
    - Because @*|node() continues to match, the recursive nature of the template
    ends up hitting every attribute and node in the XML file.
    - There is an additional template that specifically matches every node that
    is a "person" and has an attribute called "name" with a value that is not
    "David". That template is empty, so it generates no output.

    Thanks for the tip on looking up "identity transformation". I didn't know
    that's what it was called, and it helps a lot to have the nomenclature.

    David

    "roy axenov" <> wrote in message
    news:f3fdgl$1rl$...
    >
    > David Cater wrote:
    >> <people>
    >> <person name="David">
    >> Person 1 text
    >> <child age="13">Ruby</child>
    >> <child age="15">Rosie</child>
    >> </person>
    >> <person name="Wes">
    >> Person 2 text
    >> <child age="5">Erin</child>
    >> <child age="2">Rowan</child>
    >> </person>
    >> </people>
    >>

    >
    >> What if I only want to copy the nodes where person
    >> name="David"?

    >
    > <xsl:stylesheet
    > xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    > version="1.0">
    > <!-- Not to worry, m'dear boy! -->
    >
    > <!-- Captain Identity... -->
    > <xsl:template match="@*|node()">
    > <xsl:copy>
    > <xsl:apply-templates select="@*|node()"/>
    > </xsl:copy>
    > </xsl:template>
    > <!-- ...and his trusty sidekick -->
    > <!-- Exclusiontemplateman... -->
    > <xsl:template match="person[@name!='David']"/>
    > <!-- ...are gonna save the day. -->
    > </xsl:stylesheet>
    >
    David Cater, May 28, 2007
    #2
    1. Advertising

  3. David Cater

    roy axenov Guest

    David Cater wrote:
    > <people>
    > <person name="David">
    > Person 1 text
    > <child age="13">Ruby</child>
    > <child age="15">Rosie</child>
    > </person>
    > <person name="Wes">
    > Person 2 text
    > <child age="5">Erin</child>
    > <child age="2">Rowan</child>
    > </person>
    > </people>
    >
    > If I want to copy everything, I can do that with this XSL:


    [nah, that's just plain wrong.]

    > What if I only want to copy the nodes where person
    > name="David"?


    <xsl:stylesheet
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">
    <!-- Not to worry, m'dear boy! -->

    <!-- Captain Identity... -->
    <xsl:template match="@*|node()">
    <xsl:copy>
    <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
    </xsl:template>
    <!-- ...and his trusty sidekick -->
    <!-- Exclusiontemplateman... -->
    <xsl:template match="person[@name!='David']"/>
    <!-- ...are gonna save the day. -->
    </xsl:stylesheet>

    I would recommend looking up something about identity
    transformation and related topics. XSLT FAQ might be a good
    place to start.

    --
    roy axenov

    If only we smelled each other's asses, there wouldn't be any
    war.--Dustin Hoffman
    roy axenov, May 29, 2007
    #3
  4. David Cater

    Pavel Lepin Guest

    David Cater <> wrote in
    <0CH6i.20151$>:
    > "roy axenov" <> wrote in message
    > news:f3fdgl$1rl$...
    >> David Cater wrote:
    >>> What if I only want to copy the nodes where person
    >>> name="David"?

    >>
    >> <xsl:stylesheet
    >> xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    >> version="1.0">
    >> <xsl:template match="@*|node()">
    >> <xsl:copy>
    >> <xsl:apply-templates select="@*|node()"/>
    >> </xsl:copy>
    >> </xsl:template>
    >> <xsl:template match="person[@name!='David']"/>
    >> </xsl:stylesheet>
    >>

    > So based on my understanding of XSL, what that basically
    > says is:
    >
    > - Match everything that is an attribute or is a node.


    Precisely. Note that nodes are not just elements, but text
    nodes (and even more esoteric PIs and comments) as well.

    > - In that template, copy the external tag for what was
    > matched, and then apply remaining templates.


    It would be more correct to say that the template in
    question makes a shallow copy of current node or attribute
    ('tags' don't really come into it, and don't make much
    sense overall in XML world, they're just a serialization
    detail), then applies templates to all its attributes and
    children in context of this copy, but you seem to have
    grasped the idea.

    > - Because @*|node() continues to match, the recursive
    > nature of the template ends up hitting every attribute and
    > node in the XML file.


    ....unless the stylesheet excludes something (which it does).

    > - There is an additional template that specifically
    > matches every node that is a "person" and has an attribute
    > called "name" with a value that is not "David". That
    > template is empty, so it generates no output.


    Absolutely. And thanks to XSLT template specificity rules
    you don't even have to fool around with priority
    attribute - it works even without that.

    --
    Pavel Lepin
    Pavel Lepin, May 29, 2007
    #4
  5. David Cater

    Peter Flynn Guest

    David Cater wrote:
    > This seems like a simple task, but I'm banging my head against it.
    > Something about XML/XPath just isn't clicking for me yet. Here's some
    > sample XML:
    >
    > <people>
    > <person name="David">
    > Person 1 text
    > <child age="13">Ruby</child>
    > <child age="15">Rosie</child>
    > </person>


    Don't do this. Enclose the random text. Do:

    <people>
    <person name="David">
    <description>Person 1 text</description>
    <child age="13">Ruby</child>
    <child age="15">Rosie</child>
    </person>
    <person name="Wes">
    <description>Person 2 text</description>
    <child age="5">Erin</child>
    <child age="2">Rowan</child>
    </person>
    </people>

    Having loose, unmarked text floating around inside a rigid structure is
    A Bad Idea.

    Mixed Content (intermingled text and elements) is standard in the
    textual element types of normal text documents (eg within <P> in HTML)
    but almost always wrong anywhere else.

    ///Peter
    --
    XML FAQ: http://xml.silmaril.ie/
    Peter Flynn, May 31, 2007
    #5
  6. Peter Flynn wrote:
    > Having loose, unmarked text floating around inside a rigid structure is
    > A Bad Idea.


    Depends on your application. Mixed content is standard within
    document-oriented uses of XML (which includes XHTML, Docbook, and many
    others that model annotated text). It is usually -- but not always! --
    suboptimal for data-oriented uses of XML.

    "Absolutes are always inherently false. Including this one."


    --
    () ASCII Ribbon Campaign | Joe Kesselman
    /\ Stamp out HTML e-mail! | System architexture and kinetic poetry
    Joe Kesselman, May 31, 2007
    #6
  7. David Cater

    Pavel Lepin Guest

    Joe Kesselman <> wrote in
    <>:
    > Peter Flynn wrote:
    >> Having loose, unmarked text floating around inside a
    >> rigid structure is A Bad Idea.

    >
    >> Mixed Content (intermingled text and elements) is
    >> standard in the textual element types of normal text
    >> documents (eg within <P> in HTML) but almost always wrong
    >> anywhere else.

    >
    > Depends on your application. Mixed content is standard
    > within document-oriented uses of XML (which includes
    > XHTML, Docbook, and many others that model annotated
    > text). It is usually -- but not always! -- suboptimal for
    > data-oriented uses of XML.


    Well, that's precisely what Peter said (using the language
    that's probably a bit more understandable for a person new
    to XML, such as the OP).

    --
    Pavel Lepin
    Pavel Lepin, May 31, 2007
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. RanDeep
    Replies:
    2
    Views:
    1,602
    RanDeep
    Sep 26, 2003
  2. Ray Tayek
    Replies:
    3
    Views:
    515
    Ray Tayek
    Nov 30, 2003
  3. Replies:
    2
    Views:
    395
  4. Andy Fish
    Replies:
    3
    Views:
    1,009
    David Carlisle
    Feb 16, 2005
  5. William  Krick
    Replies:
    4
    Views:
    14,335
    anntenna
    Mar 18, 2011
Loading...

Share This Page