select nodes where a grandchild's text is not some value?

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • SkipSailors
    New Member
    • Sep 2008
    • 2

    select nodes where a grandchild's text is not some value?

    I have some XML that I want to transform to some XML:
    Code:
    <element>
        <child>
            <grandchild>
                otherWord
            </grandchild>
            <grandchild>
                triggerExclusion
            </grandchild>
        </child>
    </element>
    <element>
        <child>
            <grandchild>
                otherWord
            </grandchild>
        </child>
    </element>
    I want to copy elements where 'triggerExclusi on' is not the text of its grandchild subelement. In this example I want to copy the second element, not the first.

    This doesn't work for me:
    Code:
    <template match="element[not(child/grandchild eq 'triggerExclusion')"]>
        <copy>
            <apply-templates/>
        </copy>
    </template>
    My Saxon warns that a sequence can't be the first argument of the eq operator, and, I guess, only looks at the first grandchild.

    Please, how do I select elements where a descendent of arbitrary depth has some value?

    TIA
  • MarkoKlacar
    Recognized Expert Contributor
    • Aug 2007
    • 296

    #2
    Hi,

    What you could do is select every child-element that doesn't contain a grandchild with the text "triggerExclusi on".

    It could look something like this:
    (don't quite remember the syntax, but isn't text() a function that returns the value of an element?? In this case it could be "triggerExclusi on"...anyway)

    [HTML]//child/grandchild/text() != "triggerExclusi on"[/HTML]

    That should at least get you started if you haven't solved it already.

    /MK

    Comment

    • SkipSailors
      New Member
      • Sep 2008
      • 2

      #3
      thank you for the thought. This would select grandchild elements that don't have the trigger. What I want is to select elements such that the grandchild doesn't have the trigger.

      Something like --
      Code:
      //element[some test on grandchild I can't figure]

      Comment

      • Dormilich
        Recognized Expert Expert
        • Aug 2008
        • 8694

        #4
        Originally posted by SkipSailors
        thank you for the thought. This would select grandchild elements that don't have the trigger. What I want is to select elements such that the grandchild doesn't have the trigger.
        Code:
        element[child/grandchild/text() != 'triggerExclusion']
        note: about the same as in your post...

        regards

        Comment

        • jkmyoung
          Recognized Expert Top Contributor
          • Mar 2006
          • 2057

          #5
          Originally posted by Dormilich
          Code:
          element[child/grandchild/text() != 'triggerExclusion']
          note: about the same as in your post...

          regards
          Wouldn't this select the first element since it has a child/grandchild node that isn't equal to triggerExclusio n?

          I would suggest just replacing the eq with a =.

          [code=xml]
          <xsl:template match="element[not (child/grandchild = 'triggerExclusi on')]">
          <xsl:copy-of select="."/>
          </xsl:template>
          <xsl:template match="element"/>
          [/code]

          Comment

          • Dormilich
            Recognized Expert Expert
            • Aug 2008
            • 8694

            #6
            select nodes where a grandchild's text is not some value?

            Originally posted by jkmyoung
            Wouldn't this select the first element since it has a child/grandchild node that isn't equal to triggerExclusio n?
            I don't think so. It will select all <element> elements, that have not even one <grandchild> element with "triggerExcepti on". In this case, it should select the second one. note that the expression child/grandchild/text() is actually a node-set*, since there are two <grandchild> elements.

            Or to ask it the other way round: what's the difference between element[child/grandchild/text() != 'triggerExclusi on']** and element[not(child/grandchild/text() = 'triggerExclusi on')] ? to me it is the same.

            in this case (string) grandchild/text() and (string) grandchild gives the same, because there are no further child elements with text nodes (see specs @ w3c)

            * you can test it with count(child/grandchild/text()), though I'm quite positive that the result will be 2
            ** expanded XPath is child::element[child::child/child::grandchi ld/child::text()]

            Comment

            Working...