Am I the first child using an if question

E

Efi Merdler

Hi,
I have an xml file with the following structure:
<Dictionary>
....
<Nested>
<Entry>
....
</Entry>
<Entry>
....
</Entry>
</Nested>
<Entry>
</Entry>
</Dictionary>

I want to iterate over all entries and print them however there is a
special printing for entries that reside in <Nested> tags and are not
the first one.

I'm using the following code:
<xsl:for-each select="//Entry">
<p>
<!--Check if entry is part of a nested entry.-->
<xsl:if test="name(..)='Nested' and position() > 1">
<xsl:text>Print:123456</xsl:text>
</xsl:if>

The name(..)='Nested' part is working however the position part does
not, I tried to find some info on the subject with no luck.

Do you have an idea ?

Thank,
Efi
 
R

roy axenov

I have an xml file with the following structure:
<Dictionary>
...
<Nested>
<Entry>
...
</Entry>
<Entry>
...
</Entry>
</Nested>
<Entry>
</Entry>
</Dictionary>

I want to iterate over all entries and print them however
there is a special printing for entries that reside in
<Nested> tags and are not the first one.

I'm using

[for-eachs and ifs]
The name(..)='Nested' part is working however the
position part does not,

Of course it doesn't. It returns the position in the
node-set.
I tried to find some info on the subject with no luck.

Well, here's some info on the subject: you're doing it all
wrong anyway. Think about your transformations in terms of
node-sets and templates.

<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="Dictionary">
<result>
<xsl:apply-templates/>
</result>
</xsl:template>
<xsl:template match="Nested">
<xsl:apply-templates select="Entry[1]"/>
</xsl:template>
<xsl:template match="Entry">
<xsl:call-template name="Entry"/>
</xsl:template>
<xsl:template
match="Nested/Entry[not(preceding-sibling::Entry)]">
<xsl:call-template name="Entry"/>
<xsl:apply-templates
select="following-sibling::Entry"/>
</xsl:template>
<xsl:template
match="Nested/Entry[preceding-sibling::Entry]">
<special-entry>
<xsl:apply-templates/>
</special-entry>
</xsl:template>
<xsl:template name="Entry">
<normal-entry>
<xsl:apply-templates/>
</normal-entry>
</xsl:template>
</xsl:stylesheet>
 
P

Peter Flynn

Efi said:
Hi,
I have an xml file with the following structure:
<Dictionary>
...
<Nested>
<Entry>
...
</Entry>
<Entry>
...
</Entry>
</Nested>
<Entry>
</Entry>
</Dictionary>

I want to iterate over all entries and print them however there is a
special printing for entries that reside in <Nested> tags and are not
the first one.

I'm using the following code:
<xsl:for-each select="//Entry">

Don't use for-each unless you mean it (ie you want to process the
elements out of order or out of context).

If the Entry elements are already in order, then a template matching
them is all you need. If you want to sort them, however, or if you're
already processing them in document order elsewhere in your XSLT and you
now need to handle them again for some other reason, then for-each will
do it.
<p>
<!--Check if entry is part of a nested entry.-->
<xsl:if test="name(..)='Nested' and position() > 1">
<xsl:text>Print:123456</xsl:text>
</xsl:if>

The name(..)='Nested' part is working however the position part does
not, I tried to find some info on the subject with no luck.

If Entry is the context node, then

<xsl:if test="parent::Nested and count(preceding-sibling::Entry)>0">
...
</xsl:if>

will detect if the Entry is inside a Nested element and this is not the
first Entry of its group. The position() function is problematic because
it returns the position in the node-set, which may or may not be the
position in the markup. This is a usability error in XSL: position()
really ought to have been called node-position(), and position() should
have been defined with its expected meaning of "position in markup".

///Peter
 
E

Efi Merdler

Don't use for-each unless you mean it (ie you want to process the
elements out of order or out of context).

If the Entry elements are already in order, then a template matching
them is all you need. If you want to sort them, however, or if you're
already processing them in document order elsewhere in your XSLT and you
now need to handle them again for some other reason, then for-each will
do it.

///Peter

Thanks,
One more question, when using template matching only once will the
xslt engine run it in a loop when there are several matches.

For example:
<ExampleCtn>
<Example>He abandoned his family.</Example>
<Example>She was afraid of being abandoned.</Example>
</ExampleCtn>

<xsl:template match="ExampleCtn">
<xsl:text>:</xsl:text>
<xsl:value-of select="Example"/>
</xsl:template>

will value-of run in a loop on all the Example tag ?

Thanks,
Efi
 
P

p.lepin

Please don't quote the sigs and don't remove the
attributions.


For that matter, xsl:apply-templates works just nice with
xsl:sort, too. In my opinion, the rule of the thumb is:
don't use for-each unless you're dead certain you're not
pointing it at your foot. (Which you normally are.)
One more question, when using template matching only once
will the xslt engine run it in a loop when there are
several matches.

Not in a loop, there's no guaranteed order-of-execution.
But yes, if you *are* using template matching, the XSLT
processor naturally will apply templates to every node in
the node-set you've provided.
<ExampleCtn>
<Example>He abandoned his family.</Example>
<Example>She was afraid of being abandoned.</Example>
</ExampleCtn>

<xsl:template match="ExampleCtn">
<xsl:text>:</xsl:text>
<xsl:value-of select="Example"/>
</xsl:template>

will value-of run in a loop on all the Example tag ?

Why don't you stuff it in your XSLT processor and see what
happens? No, it's won't 'run in a loop' or anything like
that, because you're most emphatically *not* using template
matching in this example. Replace value-of with
apply-templates.
 

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
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top