Check for existence of a tag

T

Tassilo J. Klein

Hi there,

I got a XML file looking like that:

<Entries>
<Entry Id=1>
<First></First>
<Second></Second>
<Third></Third>
</Entry>
<Entry Id=2>
<First></First>
<Second></Second>
<Third></Third>
<Fourth></Fourth>
</Entry>.
[...]

<Entries>


I would like to check whether there exists a tag inside one of the
"Entry"s e.g. "Fourth".

I tried something like:

<xsl:template match="First">

<xsl:when test="..//Fourth">
<xsl:text>Found it</xsl:text>
</xsl:when>

<xsl:eek:therwise>
<xsl:text>Didn't find it</xsl:text>
</xsl:eek:therwise>

</xsl:template>

But it somehow doesn't work - I don't know why - probably, because I am
quite new to this ;-). Any idea?

Greetings,
- Tassilo -
 
W

William Park

Tassilo J. Klein said:
Hi there,

I got a XML file looking like that:

<Entries>
<Entry Id=1>
<First></First>
<Second></Second>
<Third></Third>
</Entry>
<Entry Id=2>
<First></First>
<Second></Second>
<Third></Third>
<Fourth></Fourth>
</Entry>.
[...]

<Entries>


I would like to check whether there exists a tag inside one of the
"Entry"s e.g. "Fourth".

To test if 'Entry' is right above 'Fourth',

start () { # Usage: start tag att=value ...
if [[ $1 == Fourth ]]; then
n=$XML_ELEMENT_STACK
if [[ ${XML_ELEMENT_STACK[n+1+1]} == Entry ]]; then
echo found Entry/Fourth
fi
fi
}
xml -s start "<Entries>...</Entries>"

To test if 'Entry' is anywhere above 'Fourth',

start () { # Usage: start tag att=value ...
if [[ $1 == Fourth ]]; then
n=$XML_ELEMENT_STACK
if [[ ${XML_ELEMENT_STACK[*]|/Entry} }}; then
echo found Entry/.../Fourth
fi
fi
}
xml -s start "<Entries>...</Entries>"

Ref:
http://freshmeat.net/projects/bashdiff/
http://home.eol.ca/~parkw/index.html#xml
help xml
 
T

Tassilo J. Klein

Ooops, I forgot to mention, that I am using XLST to produce HTML and
therefore want to make those checks using XLS.
Tassilo J. Klein said:
Hi there,

I got a XML file looking like that:

<Entries>
<Entry Id=1>
<First></First>
<Second></Second>
<Third></Third>
</Entry>
<Entry Id=2>
<First></First>
<Second></Second>
<Third></Third>
<Fourth></Fourth>
</Entry>.
[...]

<Entries>


I would like to check whether there exists a tag inside one of the
"Entry"s e.g. "Fourth".


To test if 'Entry' is right above 'Fourth',

start () { # Usage: start tag att=value ...
if [[ $1 == Fourth ]]; then
n=$XML_ELEMENT_STACK
if [[ ${XML_ELEMENT_STACK[n+1+1]} == Entry ]]; then
echo found Entry/Fourth
fi
fi
}
xml -s start "<Entries>...</Entries>"

To test if 'Entry' is anywhere above 'Fourth',

start () { # Usage: start tag att=value ...
if [[ $1 == Fourth ]]; then
n=$XML_ELEMENT_STACK
if [[ ${XML_ELEMENT_STACK[*]|/Entry} }}; then
echo found Entry/.../Fourth
fi
fi
}
xml -s start "<Entries>...</Entries>"

Ref:
http://freshmeat.net/projects/bashdiff/
http://home.eol.ca/~parkw/index.html#xml
help xml

I tried something like:

<xsl:template match="First">

<xsl:when test="..//Fourth">
<xsl:text>Found it</xsl:text>
</xsl:when>

<xsl:eek:therwise>
<xsl:text>Didn't find it</xsl:text>
</xsl:eek:therwise>

</xsl:template>

But it somehow doesn't work - I don't know why - probably, because I am
quite new to this ;-). Any idea?

Greetings,
- Tassilo -
 
K

kahrs

William said:
To test if 'Entry' is anywhere above 'Fourth',

start () { # Usage: start tag att=value ...
if [[ $1 == Fourth ]]; then
n=$XML_ELEMENT_STACK
if [[ ${XML_ELEMENT_STACK[*]|/Entry} }}; then
echo found Entry/.../Fourth
fi
fi
}
xml -s start "<Entries>...</Entries>"

Your mechanism for stacking the elements is really useful.
Quite interesting to see how you integrated this into bash.
But (as you might have guessed) I prefer the xmlgawk solution:


XMLSTARTELEM == "Fourth" { found=1 }

END {
if (found)
print "Found it"
else
print "Didn't find it"
}
 
W

William Park

kahrs said:
William said:
To test if 'Entry' is anywhere above 'Fourth',

start () { # Usage: start tag att=value ...
if [[ $1 == Fourth ]]; then
n=$XML_ELEMENT_STACK
if [[ ${XML_ELEMENT_STACK[*]|/Entry} }}; then
echo found Entry/.../Fourth
fi
fi
}
xml -s start "<Entries>...</Entries>"

Your mechanism for stacking the elements is really useful.
Quite interesting to see how you integrated this into bash.
But (as you might have guessed) I prefer the xmlgawk solution:


XMLSTARTELEM == "Fourth" { found=1 }

END {
if (found)
print "Found it"
else
print "Didn't find it"
}

Hello. But, how do you check if it's below element 'Entry'? Even if
you do something like
XMLSTARTELEM == "Entry" { foundEntry = 1 }
XMLSTARTELEM == "Fourth" && foundEntry { found = 1 }
it only tells you that Awk has encountered element 'Entry' and then
element 'Fourth'.
 
?

=?ISO-8859-1?Q?R=E9mi_Peyronnet?=

But it somehow doesn't work - I don't know why - probably, because I am
quite new to this ;-). Any idea?

1. The provided XML file is not well-formed :
<Entries>
<Entry Id=1>
^
Put this into quotes : Id="1" (same thing for Id="2")
[...]
<Entries>

Should close the tag : </Entries>

2. xsl:when and xsl;otherwise need to be in a xsl:choose element :

<xsl:choose>
<xsl:when .... > ... </xsl:when>
<xsl:eek:therwise> ... </xsl:eek:therwise>
</xsl:choose>

When these changes are done, this works perfectly :)

These typos are easily detectable with a xml editor (as cooktop by example).

Hth
 
T

Tassilo J. Klein

Well, thanks - but the mistakes you mentioned I just forgot in the
message I posted but I actually had it in my .xsl file.

But thanks even though :)

Rémi Peyronnet said:
But it somehow doesn't work - I don't know why - probably, because I
am quite new to this ;-). Any idea?


1. The provided XML file is not well-formed :
<Entries>
<Entry Id=1>
^
Put this into quotes : Id="1" (same thing for Id="2")
[...]
<Entries>

Should close the tag : </Entries>

2. xsl:when and xsl;otherwise need to be in a xsl:choose element :

<xsl:choose>
<xsl:when .... > ... </xsl:when>
<xsl:eek:therwise> ... </xsl:eek:therwise>
</xsl:choose>

When these changes are done, this works perfectly :)

These typos are easily detectable with a xml editor (as cooktop by
example).

Hth
 
K

kahrs

William said:
Hello. But, how do you check if it's below element 'Entry'? Even if
you do something like
XMLSTARTELEM == "Entry" { foundEntry = 1 }
XMLSTARTELEM == "Fourth" && foundEntry { found = 1 }
it only tells you that Awk has encountered element 'Entry' and then
element 'Fourth'.

Correct, your bash solutions uses the bash-internal element
stack and searches in it for "Fourth". In xmlgawk, I have
to emulate the element stack with gawk's associative arrays:

BEGIN { XMLMODE=1 ; found="Didn't find it" }

XMLSTARTELEM { elms[XMLSTARTELEM]=1 }

XMLENDELEM { delete elms[XMLSTARTELEM] }

XMLSTARTELEM == "Fourth" {
found="Found it"
if ("Entry" in elms)
print "'Fourth' is under 'Entry'"
else
print "'Fourth' is not under 'Entry'"
}

END { print found }
 
W

William Park

kahrs said:
William said:
Hello. But, how do you check if it's below element 'Entry'? Even if
you do something like
XMLSTARTELEM == "Entry" { foundEntry = 1 }
XMLSTARTELEM == "Fourth" && foundEntry { found = 1 }
it only tells you that Awk has encountered element 'Entry' and then
element 'Fourth'.

Correct, your bash solutions uses the bash-internal element
stack and searches in it for "Fourth". In xmlgawk, I have
to emulate the element stack with gawk's associative arrays:

BEGIN { XMLMODE=1 ; found="Didn't find it" }

XMLSTARTELEM { elms[XMLSTARTELEM]=1 }

XMLENDELEM { delete elms[XMLSTARTELEM] }

XMLSTARTELEM == "Fourth" {
found="Found it"
if ("Entry" in elms)

Okey, I got it. Much cleaner than I'd imagined.
 
P

Patrick TJ McPhee

% Ooops, I forgot to mention, that I am using XLST to produce HTML and
% therefore want to make those checks using XLS.

An XPath which matches all Entry elements which contain a Fourth element is

//Entry[Fourth]

You can use this as part of a test, match, or select expression in XSLT. For
instance (you don't need // xsl:template's match attribute)

<xsl:template match='Entry[Fourth]'>
My favourite Entry is number <xsl:value-of select='@Id'/>.
</xsl:template>

or (ok, this isn't quite the same expression)

<xsl:template match='Entry'>
Blah blah blah
<xsl:if test='Fourth'>
This Entry has a Fourth element.
</xsl:if>
</xsl:template>

or how about

<xsl:template match='/'>
We do something with all Entry elements containing fourth:
<xsl:apply-templates mode='withfourth' select='//Entry[Fourth]'/>
Then we do something else with the whole document:
<xsl:apply-templates/>
</xsl:template>

<xsl:template mode='withfourth' match="*">
Blah blah blah.
</xsl:template>

...
 

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,997
Messages
2,570,240
Members
46,830
Latest member
HeleneMull

Latest Threads

Top