cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
Showing results for 
Search instead for 
Did you mean: 

Community Tip - You can subscribe to a forum, label or individual post and receive email notifications when someone posts a new topic or reply. Learn more! X

help with XPATH

cleccese
6-Contributor

help with XPATH

how can I have a tag check its content? I can't use starts-with because I want the answer to be "1" and there is also a "10".


I am looking for when hazid = 1 or the first time hazid has content.


(And how would another tag check hazid's content?)



Thanks!

14 REPLIES 14

If you're "on" hazid, you could do: self::hazid[. = '1']
or just: self::*[. = '1']

If you're on, say, the parent of hazid: child::hazid[. = '1']
or just: hazid[. = '1'] (since "child" is the default axis, or "direction
of travel within the tree/graph/document")

If you need to get to hazid from somewhere else, please describe it.

By way of explanation, "." is short for "self::node()", a.k.a. "the current
node". Comparing it with a string ('1') causes XPath to take the "string
value" of the node, which is all of the text content (recursively), for an
element.

-Brandon 🙂


On Mon, Apr 23, 2012 at 10:22 PM, Caroline Leccese <
caroline@thecodesource.net> wrote:

> how can I have a tag check its content? I can't use starts-with because I
> want the answer to be "1" and there is also a "10".
>
> I am looking for when hazid = 1 or the first time hazid has content.
>
> (And how would another tag check hazid's content?)
>
>
>
> Thanks!
>
cleccese
6-Contributor
(To:cleccese)

Thanks Brandon! I want to check from <icon>


<exp>


<icon><title></title><hazid></hazid><hazdesc></hazdesc>


<icon><title></title><hazid></hazid><hazdesc></hazdesc>


<icon><title></title><hazid></hazid><hazdesc></hazdesc>


</exp>

cleccese
6-Contributor
(To:cleccese)

from icon: following-sibling::hazid[. = '1']


is not right...it is coming up true when hazid is empty as well as when hazid = 1

you could try combining with thenormalize-space() function

Tracey

On Thu, Apr 26, 2012 at 1:38 PM, Caroline Leccese
<caroline@thecodesource.net> wrote:
>
> following-sibling::hazid[. = '1']
>
> is not right...it is coming up true when hazid is empty as well as when hazid = 1
>
>
> -----End Original Message-----

From your example, it seemed like you should be using the "child" axis (or
none at all, since "child" is the default), rather than
"following-sibling", since you indicated that your context was an element
that appeared to be the parent of "hazid".

Can you give us more details of the case where you're not getting the
results you expect? A document fragment including both the hazid you're
looking at, as well as the context element. Also, how are these XPath
expressions being evaluated? In Styler, using ACL functions in Editor, in
something completely different...?

-Brandon 🙂


On Wed, Apr 25, 2012 at 11:38 PM, Caroline Leccese <
caroline@thecodesource.net> wrote:

> following-sibling::hazid[. = '1']
>
> is not right...it is coming up true when hazid is empty as well as when
> hazid = 1
>
cleccese
6-Contributor
(To:cleccese)

My mistake, <icon/> is a single tag, it is not the parent of hazid (as I understand it)


Via styler 5.4, I am inserting a condition onto <icon/> using xpath: following-sibling::hazid[. = '1'] is true


If I put test gentext "


<exp>


TRUE <icon><title>title</title> <hazid></hazid><hazdesc>text.</hazdesc>


TRUE<icon><title>title</title><hazid>2</hazid><hazdesc>text</hazdesc>


<icon><title>title</title><hazid>4</hazid><hazdesc>text</hazdesc>


</exp>



Thanks for any help!

As Tracey mentioned, use

At icon element, use the following xpath:
following-sibling::hazid[normalise-space(.) = '1']


On Thu, Apr 26, 2012 at 4:58 PM, Caroline Leccese <
caroline@thecodesource.net> wrote:

> My mistake, <icon/> is a single tag, it is not the parent of hazid (as I
> understand it)
>
> Via styler 5.4, I am inserting a condition onto <icon/> using xpath:
> following-sibling::hazid[. = '1'] is true
>
> If I put test gentext "*TRUE*" before icon for the condition, this is
> what happens:
>
> <exp>
>
> *TRUE*<icon><title>title</title>*<hazid></hazid>*<hazdesc>text.</hazdesc>
>
> *TRUE*<icon><title>title</title>*<hazid></hazid>*<hazdesc>text.</hazdesc>
>
> *TRUE*<icon><title>title</title>*<hazid></hazid>*<hazdesc>text.</hazdesc>
>
> *TRUE*<icon><title>title</title>*<hazid>1</hazid>*<hazdesc>text</hazdesc>
>
> <icon><title>title</title>*<hazid>2</hazid>*<hazdesc>text</hazdesc>
>
> <icon><title>title</title>*<hazid>3</hazid>*<hazdesc>text</hazdesc>
>
> <icon><title>title</title>*<hazid>4</hazid>*<hazdesc>text</hazdesc>
>
> </exp>
>

Let's break the XPath down to see why this is happening. The first part,
"following-sibling::hazid", returns a node-set consisting of all of the
"hazid" elements that follow the context node and are children of the same
parent element. In your example, this is every hazid until the closing
"exp" tag.

The second part, "[. = '1']", filters the set of nodes to just those for
which the string-value of the node (".") is equal to the string "1".
Because we're evaluating this is a boolean (true/false) condition, XPath
then converts the node-set to a boolean value, for which the rule is to
return false if the node-set is empty and true otherwise.

Since the first four "icon" elements are all followed by a "hazid" whose
content is equal to "1", they all match the condition. It seems that your
real requirement is to match those "icon" elements for which the *next*
"hazid" is equal to "1". For this, we can include a "positional"
predicate, as follows:

following-sibling::hazid[1][. = '1']

Here, the "[1]" filters the node-set to just the first item within it, then
applies the content-based filter, as before.

For the record, the "normalize-space" function can be very useful in
dealing with arbitrary data which may contain arbitrary white space, and I
wouldn't disagree with using it here, in addition to the above change, to
make the condition more robust.

-Brandon 🙂


On Thu, Apr 26, 2012 at 12:58 AM, Caroline Leccese <
caroline@thecodesource.net> wrote:

> My mistake, <icon/> is a single tag, it is not the parent of hazid (as I
> understand it)
>
> Via styler 5.4, I am inserting a condition onto <icon/> using xpath:
> following-sibling::hazid[. = '1'] is true
>
> If I put test gentext "*TRUE*" before icon for the condition, this is
> what happens:
>
> <exp>
>
> *TRUE*<icon><title>title</title>*<hazid></hazid>*<hazdesc>text.</hazdesc>
>
> *TRUE*<icon><title>title</title>*<hazid></hazid>*<hazdesc>text.</hazdesc>
>
> *TRUE*<icon><title>title</title>*<hazid></hazid>*<hazdesc>text.</hazdesc>
>
> *TRUE*<icon><title>title</title>*<hazid>1</hazid>*<hazdesc>text</hazdesc>
>
> <icon><title>title</title>*<hazid>2</hazid>*<hazdesc>text</hazdesc>
>
> <icon><title>title</title>*<hazid>3</hazid>*<hazdesc>text</hazdesc>
>
> <icon><title>title</title>*<hazid>4</hazid>*<hazdesc>text</hazdesc>
>
> </exp>
>
cleccese
6-Contributor
(To:cleccese)

Thanks, everyone!


following-sibling::hazid[1][normalize-space(.) = '1'] worked as I wished.


Is there a way to write the condition in Styler so it doesn't convert to a Boolean and just checks the value?

Hello,

Why don't you use the simple test :
following-sibling::hazid[text()='1']

does it also return true when hazid is empty ?

Yves Deniard
MBDA France

I oversimplified a bit in just saying that XPath converts the value to a
boolean. The XPath engine does the conversion at the request of the
caller, since it wants a boolean value in order to decide if it should
proceed with the condition.

Depending on which output type you're working with, doing a "View Source"
in Styler and searching for your XPath expression will probably turn up
that it has been wrapped in a call to the "boolean" XPath function, which
does the conversion. Some outputs won't have this call, since the context
(such as the "test" attribute of an xsl:if or xsl:when, for an XSLT-based
output) implies a boolean conversion.

-Brandon 🙂


On Thu, Apr 26, 2012 at 1:46 AM, Caroline Leccese <
caroline@thecodesource.net> wrote:

> Thanks, everyone!
>
> following-sibling::hazid[1][normalize-space(.) = '1'] worked as I wished.
>
> I didn't know that XPATH converts the value to a boolean. How would you
> get it to return the actual value?
>

The issue that was causing the undesired results in this case was the
presence of multiple "hazid" elements, all of which were following siblings
of the context node, an "icon" element. The expression suggested below
would return any such element that matched the "[text()='1']" predicate,
but what is desired is for the condition to only return true if the first
such element matches, thus the addition of the "[1]" predicate.

The change suggested here, using "text()" instead of ".", would work for
the given use case, though it probably would not provide any advantage and
may even fail in certain cases where "." would not. The difference is that
while "." will concatenate all of the text contained within the "hazid"
element, at any level, "text()" will only check that some contiguous string
of text immediately inside of the "hazid" matches the "1" string. If there
is any other markup inside of the "hazid" element, such as
"<hazid><value>1</value></hazid>", this test would fail, since the "1" text
node is not an immediate child of "hazid".

Another edge case where the difference might be seen is a PI occurring
between two characters. Say you're looking for "12" instead of just "1".
If you happen to have saved your document with the cursor in the wrong
place, your style sheet might get something like "<hazid>1Caret?>2</hazid>". Since there is no text node here with a string value of
"12" (the "1" and "2" are two separate nodes), the test would fail.

-Brandon 🙂


On Thu, Apr 26, 2012 at 4:58 AM, DENIARD.Yves <yves.deniard@mbda-systems.com<br/>> wrote:

> ****
>
> Hello,****
>
> ** **
>
> Why don’t you use the simple test :****
>
> following-sibling::hazid[text()=’1’]****
>
> ** **
>
> does it also return true when hazid is empty ?****
>
> ** **
>
> Yves Deniard****
>
> MBDA ****France********
cleccese
6-Contributor
(To:cleccese)

following-sibling::hazid[text()='1'] returned the same results as following-sibling::hazid[. = '1'] with TRUE in the empty hazids.

From a co-worker:

I want to know when the value of a specific attribute on a specific tag has changed. I was hoping there would be an event/callback available for the Modify Attributes dialog - for instance, after the OK button is clicked - but I can only find a "before" event ("modify_tag" allows you to modify values and behavior before the dialog appears). Is the answer to use the "dlgitem_add_callback" function? If so, how do I use that set of functions to zero in on Modify Attributes, while knowing the tag and changed attribute(s)?

I'm having trouble with the PDF Customizer's Guide, which may have answers, so I'm taking the easy route for now!

Top Tags