3

I've the below XML.

<section level="sect1">
    <title>
      <page num="1150"/>
      <content-style font-style="bold">ORDER 62</content-style>
      <content-style format="smallcaps">Costs</content-style>
    </title>
</section>

Here i want to check if the title has word ORDER in it.

I've tried

contains(//section[1]/title[1]/content-style[1]/text(),'ORDER')

but there are instances where the string ORDER might be in 2nd content-style` or in some might be in 3rd.

please let me know a generic way of finding it.

Thanks

Dimitre Novatchev
  • 240,661
  • 26
  • 293
  • 431
user3872094
  • 3,269
  • 8
  • 33
  • 71

4 Answers4

1
contains(//section[1]/title[1]/content-style[1]/text(),'ORDER')

You do a contains on the whole path, explicitly saying, in this expression, to get the first of each element with [1]. Instead, from your description you want the child content-style that has "ORDER" in it, which you should do as follows:

//section[1]/title[1]/content-style[text() = 'ORDER']

Or, if whitespace can be added:

//section[1]/title[1]/content-style[normalize-space(text()) = 'ORDER']

If the result is non-empty, you have found at least one "ORDER" in any content-style below title[1], below section[1].

get grand child text from grand parent element

This was your question title. It is slightly different from what you wrote. If you want to check for any grand-child content-style from section then do this:

//section[1]/*/content-style[normalize-space(text()) = 'ORDER']

Final note: you tagged your original question as , in XSLT, an if-condition does not need to be a boolean, so:

<xsl:if test="//section[1]/*/content-style[normalize-space(text()) = 'ORDER']">
    <hello>found it!</hello>
</xsl:if>

is equal to wrapping the whole thing in contains, except that with contains you would be checking to a string combined of all elements, which would also mach 'no such ORDER', for instance.

The above is also similar to:

<!-- in place of xsl;if -->
<xsl:apply-templates select="//section[1]/*/content-style" />

<!-- place this at root level anywhere -->
<xsl:template match="content-style[normalize-space(text()) = 'ORDER']">
    <hello>found it!</hello>
</xsl:template>

<xsl:template match="content-style">
    <hello>Not an order!</hello>
</xsl:template>
Abel
  • 56,041
  • 24
  • 146
  • 247
1

You want

exists(//section[1]/title/content-style[contains(., 'ORDER')])
Dimitre Novatchev
  • 240,661
  • 26
  • 293
  • 431
Michael Kay
  • 156,231
  • 11
  • 92
  • 164
1

Here i want to check if the title has word ORDER in it.

I've tried

contains(//section[1]/title[1]/content-style[1]/text(),'ORDER')

but there are instances where the ORDER might be in 2nd content-style` or in some might be in 3rd.

please let me know a generic way of finding it.

Here is one XPath 1.0 expression that produces exactly the wanted Boolean value:

boolean((//section)[1]/title[1][content-style[contains(., 'ORDER')]])

This produces true() exactly when there is at least one content-style element that is a child of a title element that is the first child of the first section element in the XML document.

And a corresponding XPath 2.0 expression:

exists((//section)[1]/title[1][content-style[contains(., 'ORDER')]])
Dimitre Novatchev
  • 240,661
  • 26
  • 293
  • 431
0

I think you need to obtain all the text from below the "title" node. The following should work:

contains(//section[1]/title[1]/string(.),'ORDER')

at least according to this reference

Vicky
  • 12,934
  • 4
  • 46
  • 54
  • No, this is not the same, as it will also include text in `page`, any mixed content in `title[1]` and possibly other elements at that level. – Abel Sep 11 '15 at 12:13