Exclude node during searches

Questions about XML that are not covered by the other forums should go here.
jorusso
Posts: 4
Joined: Fri Jul 20, 2012 1:05 am

Exclude node during searches

Post by jorusso »

I'm in DITA and my goal is to search for text that is not inside a particular element. For example I want to search for "ABC Corp." that is not inside <codeblock>. I should be able to specify any of the following Xpath statements:
  • //*[(name()!='codeblock')]
    //*[not(self::codeblock)]
    //*[not(codeblock)]
All of these give the expected results in the XPath field on the toolbar. However, none of them work when I use them in the XPath field in the Find dialog box.

What am I doing wrong?
Jamil
Posts: 97
Joined: Thu Oct 23, 2008 6:29 am

Re: Exclude node during searches

Post by Jamil »

I had never used the XPath input on the find dialog. It could very well be an issue with it.

What you could do instead is write an XQuery to show you what you are looking for. The Saxon extensions for it can show the line numbers of the XML document.
jorusso
Posts: 4
Joined: Fri Jul 20, 2012 1:05 am

Re: Exclude node during searches

Post by jorusso »

Thanks, Jamil.

I've been looking for an excuse to study XQuary, anyway!
So having a real-world need is perfect. :shock:
adrian
Posts: 2855
Joined: Tue May 17, 2005 4:01 pm

Re: Exclude node during searches

Post by adrian »

Hello,

The problem with the XPath expressions you're using is that even though they exclude the codeblock element, they don't exclude any of codeblock's parent elements. Find will search in the most extensive range selected by the XPath (it merges the XPath results), which in all cases for your expressions includes the root element and everything in it.
So, in short the expressions you are using don't filter what you want.

If you want to search only within text that is not inside <codeblock>, you could specify that clearly in the XPath expression:

Code: Select all

//text()[not(ancestor::codeblock)]
Or if you want to also search across multiple (text) nodes (e.g. text with markup) you can use in the XPath field:

Code: Select all

//*[not(descendant-or-self::codeblock)]|//text()[not(ancestor::codeblock)]
XQuery is pretty powerful, but you'll still need XPath there as well.

Regards,
Adrian
Adrian Buza
<oXygen/> XML Editor, Schema Editor and XSLT Editor/Debugger
http://www.oxygenxml.com
jorusso
Posts: 4
Joined: Fri Jul 20, 2012 1:05 am

Re: Exclude node during searches

Post by jorusso »

Adrian,

Thanks for the helpful reply! Sorry it took so long to reply, I forgot to log back in to check for a reply.

Can you offer any recommendations on learning XPath? I've done the W3 tutorial and know just enough to get myself in trouble!

-joe
adrian
Posts: 2855
Joined: Tue May 17, 2005 4:01 pm

Re: Exclude node during searches

Post by adrian »

Hi,

Unfortunately most online tutorials are for the beginner level, so they overlap a lot.
You could also give zvon.org a try:
http://zvon.org/comp/r/tut-XPath_1.html

As usual, experience is the best teacher, so you should try various things on your own. When something doesn't work as you expect it, search the web for answers.

Regards,
Adrian
Adrian Buza
<oXygen/> XML Editor, Schema Editor and XSLT Editor/Debugger
http://www.oxygenxml.com
shudson310
Posts: 156
Joined: Sat Feb 26, 2005 12:09 am
Location: USA
Contact:

Re: Exclude node during searches

Post by shudson310 »

Here's a related question:

We want to find:

Code: Select all

<wintitle>some text</wintitle>
and replace with:

Code: Select all

<wintitle keyref="someKey" />
We've tried restricting the XPath to:

Code: Select all

//*[not(descendant-or-self::alt|descendant-or-self::title|descendant-or-self::shortdesc|descendant-or-self::draft-comment)]|//text()[not(ancestor::alt|ancestor::title|ancestor::shortdesc|ancestor::draft-comment)]
Unfortunately, we are still getting results within shortdesc, so the exclusion doesn't appear to work. I think this is due to the fact that we are trying to modify an element node and turn it into a keyref.

Any suggestions on how to search/replace across files with the exclusions we're trying to achieve?
Scott Hudson
Staff Content Engineer
Site: docs.servicenow.com
adrian
Posts: 2855
Joined: Tue May 17, 2005 4:01 pm

Re: Exclude node during searches

Post by adrian »

Hi,

There is a mistake in my XPath (from 4 years ago) that covers elements and text (for text with markup). It should be:

Code: Select all

//*[not(descendant-or-self::codeblock|ancestor::codeblock)]|//text()[not(ancestor::codeblock)]
This way it won't accept
So, try this one (note that you don't need the //text if you're searching markup):

Code: Select all

//*[not(descendant-or-self::alt|descendant-or-self::title|descendant-or-self::shortdesc|descendant-or-self::draft-comment|ancestor::alt|ancestor::title|ancestor::shortdesc|ancestor::draft-comment)]
Regards,
Adrian
Adrian Buza
<oXygen/> XML Editor, Schema Editor and XSLT Editor/Debugger
http://www.oxygenxml.com
shudson310
Posts: 156
Joined: Sat Feb 26, 2005 12:09 am
Location: USA
Contact:

Re: Exclude node during searches

Post by shudson310 »

That worked perfectly. Thanks for the quick, expert help!
Scott Hudson
Staff Content Engineer
Site: docs.servicenow.com
Post Reply