Check for existence of a tag

Discussion in 'XML' started by Tassilo J. Klein, Aug 20, 2004.

  1. 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 -
     
    Tassilo J. Klein, Aug 20, 2004
    #1
    1. Advertising

  2. Tassilo J. Klein

    William Park Guest

    Tassilo J. Klein <> wrote:
    > 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 -


    --
    William Park <>
    Open Geometry Consulting, Toronto, Canada
     
    William Park, Aug 20, 2004
    #2
    1. Advertising

  3. 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 <> wrote:
    >
    >>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 -

    >
    >
     
    Tassilo J. Klein, Aug 20, 2004
    #3
  4. Tassilo J. Klein

    kahrs Guest

    William Park wrote:

    > 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"
    }
     
    kahrs, Aug 20, 2004
    #4
  5. Tassilo J. Klein

    William Park Guest

    kahrs <> wrote:
    > William Park wrote:
    >
    > > 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'.

    --
    William Park <>
    Open Geometry Consulting, Toronto, Canada
     
    William Park, Aug 21, 2004
    #5
  6. > 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

    --
    Rémi Peyronnet
     
    =?ISO-8859-1?Q?R=E9mi_Peyronnet?=, Aug 21, 2004
    #6
  7. 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 wrote:
    >> 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
    >
     
    Tassilo J. Klein, Aug 21, 2004
    #7
  8. Tassilo J. Klein

    kahrs Guest

    William Park wrote:

    > 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 }
     
    kahrs, Aug 21, 2004
    #8
  9. Tassilo J. Klein

    William Park Guest

    kahrs <> wrote:
    > William Park wrote:
    >
    > > 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.

    > print "'Fourth' is under 'Entry'"
    > else
    > print "'Fourth' is not under 'Entry'"
    > }
    >
    > END { print found }


    --
    William Park <>
    Open Geometry Consulting, Toronto, Canada
     
    William Park, Aug 21, 2004
    #9
  10. In article <cg5mdm$8nt$04$-online.com>,
    Tassilo J. Klein <> wrote:
    % 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>

    ...
    --

    Patrick TJ McPhee
    East York Canada
     
    Patrick TJ McPhee, Aug 23, 2004
    #10
    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. Leon
    Replies:
    1
    Views:
    443
    John Timney \(Microsoft MVP\)
    Oct 18, 2003
  2. TaeHo Yoo
    Replies:
    3
    Views:
    5,993
    John Timney \(Microsoft MVP\)
    Oct 20, 2003
  3. CK
    Replies:
    5
    Views:
    24,344
    Lars-Inge Tønnessen \(VJ# MVP\)
    Mar 21, 2006
  4. shruds
    Replies:
    1
    Views:
    933
    John C. Bollinger
    Jan 27, 2006
  5. Replies:
    3
    Views:
    2,986
    Gordon Beaton
    Apr 17, 2006
Loading...

Share This Page