Matching twice

P

patrik.nyman

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
 
P

p.lepin

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).
 
P

patrik.nyman

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
 
P

p.lepin

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.
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.
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.
 
P

patrik.nyman

Thanks a lot, Pavel, for these clarifications.

/Patrik

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.
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.
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.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,007
Messages
2,570,266
Members
46,864
Latest member
DaniEbswor

Latest Threads

Top