Matching twice

Discussion in 'XML' started by patrik.nyman@orient.su.se, Dec 13, 2006.

  1. Guest

    Hi!

    I have elements like these:

    <name style="it">SomeData</name>
    <otherName style="it">SomeOtherData</otherName>

    and tries to transform these with the following:

    <xsl:template match="*[@style='it']">
    <i><xsl:apply-templates/></i>
    </xsl:template>

    <xsl:template match="name">
    ... do something ...
    </xsl:template>

    <xsl:template match="otherName">
    ... do something ...
    </xsl:template>

    But as you might guess, it does not work, because only
    the first template matches. That is, after the first
    template there is

    <i>SomeData</i>

    but I would like to have

    <name><i>SomeData</i></name>

    Could someone please tell me how?

    /Patrik
    , Dec 13, 2006
    #1
    1. Advertising

  2. Guest

    wrote:
    > I have elements like these:
    >
    > <name style="it">SomeData</name>
    > <otherName style="it">SomeOtherData</otherName>
    >
    > and tries to transform these with the following:
    >
    > <xsl:template match="*[@style='it']">
    > <i><xsl:apply-templates/></i>
    > </xsl:template>
    >
    > <xsl:template match="name">
    > ... do something ...
    > </xsl:template>
    >
    > <xsl:template match="otherName">
    > ... do something ...
    > </xsl:template>


    You really should define 'do something', because the
    solutions possible depend on what you're trying to do with
    the elements.

    For example:

    <xsl:template match="text()[../@style='it']">
    <i><xsl:copy/></i>
    </xsl:template>

    This template will process all the text nodes that are
    children of elements with style attribute being equal to
    'it', BUT, it will only work if you're not trying to do
    anything with text nodes when you match the corresponding
    elements. And, of course, you'll have to add
    <xsl:apply-templates select="text()"/> or somesuch
    somewhere (or simply use the identity transformation).

    --
    Pavel Lepin
    , Dec 13, 2006
    #2
    1. Advertising

  3. Guest

    wrote:

    > You really should define 'do something', because the
    > solutions possible depend on what you're trying to do with
    > the elements.
    >
    > For example:
    >
    > <xsl:template match="text()[../@style='it']">
    > <i><xsl:copy/></i>
    > </xsl:template>
    >
    > This template will process all the text nodes that are
    > children of elements with style attribute being equal to
    > 'it',


    This is an abbrevated verion of a template:

    <xsl:template match="name">
    <xsl:variable name="info" select="@flag"/>
    <xsl:variable name="link" select="@url"/>
    <a title="{$info}" href="{$link}"
    target="_blank"><xsl:apply-templates/></a>
    </xsl:template>

    It seems to work fine with your code.

    > BUT, it will only work if you're not trying to do
    > anything with text nodes when you match the corresponding
    > elements.


    This I cannot follow, could you please give an example?

    > And, of course, you'll have to add
    > <xsl:apply-templates select="text()"/> or somesuch
    > somewhere (or simply use the identity transformation).


    The simple <xsl:apply-templates/> seems to work in my case.
    Are there any possible drawbacks, or specific situations where
    <xsl:apply-templates select="text()"/> should rather be used.

    Thanks a lot for your help, Pavel!

    /Patrik
    , Dec 13, 2006
    #3
  4. Guest

    wrote:
    > wrote:
    > > You really should define 'do something', because the
    > > solutions possible depend on what you're trying to do
    > > with the elements.
    > >
    > > For example:
    > >
    > > <xsl:template match="text()[../@style='it']">
    > > <i><xsl:copy/></i>
    > > </xsl:template>
    > >
    > > This template will process all the text nodes that are
    > > children of elements with style attribute being equal
    > > to 'it',

    >
    > This is an abbrevated verion of a template:
    >
    > <xsl:template match="name">
    > <xsl:variable name="info" select="@flag"/>
    > <xsl:variable name="link" select="@url"/>
    > <a title="{$info}" href="{$link}"
    > target="_blank"><xsl:apply-templates/></a>


    Oh, great, that's how it really should be done.

    > </xsl:template>
    >
    > It seems to work fine with your code.


    As it should.

    > > BUT, it will only work if you're not trying to do
    > > anything with text nodes when you match the
    > > corresponding elements.

    >
    > This I cannot follow, could you please give an example?


    Well, consider the following example:

    <xsl:template match="name">
    <xsl:copy>
    <xsl:value-of
    select=
    "
    translate
    (
    .,
    'abcdefghijklmnopqrstuvwxyz',
    'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
    )
    "/>
    </xsl:copy>
    </xsl:template>

    If you processed your text nodes that way, obviously, my
    solution wouldn't work, because templates would never be
    applied to them. That's one of the reasons to stick to
    template-based processing whenever you can.

    > > And, of course, you'll have to add
    > > <xsl:apply-templates select="text()"/> or somesuch
    > > somewhere (or simply use the identity transformation).

    >
    > The simple <xsl:apply-templates/> seems to work in my
    > case.


    If select attribute is omitted, templates are applied to
    all child::node()s, which includes all the text node
    children.

    > Are there any possible drawbacks, or specific situations
    > where <xsl:apply-templates select="text()"/> should
    > rather be used.


    If you need to process text nodes only, you should use
    text(). If you need to process all the children nodes,
    <xsl:apply-templates/> should be used. In my example, I
    used <xsl:apply-templates select="text()"/> for clarity's
    sake.

    --
    Pavel Lepin
    , Dec 13, 2006
    #4
  5. Guest

    Thanks a lot, Pavel, for these clarifications.

    /Patrik

    wrote:
    > wrote:
    > > wrote:
    > > > You really should define 'do something', because the
    > > > solutions possible depend on what you're trying to do
    > > > with the elements.
    > > >
    > > > For example:
    > > >
    > > > <xsl:template match="text()[../@style='it']">
    > > > <i><xsl:copy/></i>
    > > > </xsl:template>
    > > >
    > > > This template will process all the text nodes that are
    > > > children of elements with style attribute being equal
    > > > to 'it',

    > >
    > > This is an abbrevated verion of a template:
    > >
    > > <xsl:template match="name">
    > > <xsl:variable name="info" select="@flag"/>
    > > <xsl:variable name="link" select="@url"/>
    > > <a title="{$info}" href="{$link}"
    > > target="_blank"><xsl:apply-templates/></a>

    >
    > Oh, great, that's how it really should be done.
    >
    > > </xsl:template>
    > >
    > > It seems to work fine with your code.

    >
    > As it should.
    >
    > > > BUT, it will only work if you're not trying to do
    > > > anything with text nodes when you match the
    > > > corresponding elements.

    > >
    > > This I cannot follow, could you please give an example?

    >
    > Well, consider the following example:
    >
    > <xsl:template match="name">
    > <xsl:copy>
    > <xsl:value-of
    > select=
    > "
    > translate
    > (
    > .,
    > 'abcdefghijklmnopqrstuvwxyz',
    > 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
    > )
    > "/>
    > </xsl:copy>
    > </xsl:template>
    >
    > If you processed your text nodes that way, obviously, my
    > solution wouldn't work, because templates would never be
    > applied to them. That's one of the reasons to stick to
    > template-based processing whenever you can.
    >
    > > > And, of course, you'll have to add
    > > > <xsl:apply-templates select="text()"/> or somesuch
    > > > somewhere (or simply use the identity transformation).

    > >
    > > The simple <xsl:apply-templates/> seems to work in my
    > > case.

    >
    > If select attribute is omitted, templates are applied to
    > all child::node()s, which includes all the text node
    > children.
    >
    > > Are there any possible drawbacks, or specific situations
    > > where <xsl:apply-templates select="text()"/> should
    > > rather be used.

    >
    > If you need to process text nodes only, you should use
    > text(). If you need to process all the children nodes,
    > <xsl:apply-templates/> should be used. In my example, I
    > used <xsl:apply-templates select="text()"/> for clarity's
    > sake.
    >
    > --
    > Pavel Lepin
    , Dec 13, 2006
    #5
    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. Matching twice

    , Dec 13, 2006, in forum: XML
    Replies:
    0
    Views:
    378
  2. Kiuhnm

    twice(twice(x))

    Kiuhnm, Apr 1, 2006, in forum: C++
    Replies:
    2
    Views:
    393
    Kiuhnm
    Apr 1, 2006
  3. Joel VanderWerf
    Replies:
    1
    Views:
    221
    Joel VanderWerf
    Nov 10, 2006
  4. Marc Bissonnette

    Pattern matching : not matching problem

    Marc Bissonnette, Jan 8, 2004, in forum: Perl Misc
    Replies:
    9
    Views:
    230
    Marc Bissonnette
    Jan 13, 2004
  5. Bobby Chamness
    Replies:
    2
    Views:
    224
    Xicheng Jia
    May 3, 2007
Loading...

Share This Page