Retrieve a tag's value using XPATH depending if a different tag exists or not

N M
N M used Ask the Experts™
on
I have an XML document and I need to read a specific value by calling XPATH.
My problem is that, when a tag A is present (no matter if has value or not, just be present in the document), I have to read tags X1 and X2. Otherwise I have to read another pair of tags.

Example: below, if "mytagA" exists somewhere, I have to search and get X1 ("1000") and X2 ("MAN")

<test>
<component>
  <mytagA>something</mytagA>
</component>
...
<X1>1000</X1>
<X2>MAN</X2>
</test>

Open in new window


However, below the tag "mytagA" does not exist and in this case I need to read Y1 ("123.45") and Y2 ("ORANGE")

<test>
<component>
  <mytagB>another thing</mytagA>
</component>
...
<Y1>123.45</Y1>
<Y2>ORANGE</Y2>
</test>

Open in new window



How can I do this with one XPATH one-line function ?
Reason is I am calling the XPATH from a program, and the program fails because of this "if exists" problem...

Can you help me?
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Gertone (Geert Bormans)Information Architect
Top Expert 2006

Commented:
Note that your XML is not wellformed

//X1[//mytagA] | //X2[//mytagA] | //Y1[not(//mytagA)] | //Y2[not(//mytagA)]

is a direct translation of what you need to XPath
However that would not be the most efficient solution
For a better solution we need more context
N MConsultant

Author

Commented:
Sorry for the orthographic mistake in second XML, I wrote them by hand
Here is the corrected (the "mytagB" closes with an equal "/mytagB" tag)

<test>
<component>
  <mytagB>another thing</mytagB>
</component>
...
<Y1>123.45</Y1>
<Y2>ORANGE</Y2>
</test>

Open in new window


Obviously the three dots "..." imply more tags are there (irrelevant). What more context is needed?


I could provide the logic in form of pseudo code, hoping that could clarify more?


IF tag("mytagA") Exists Then
  return ("./test/X1/text()")
  return ("./test/X2/text()")
ELSE
  IF tag("mytagB") Exists Then       'just checking if exists otherwise no point
    return ("./test/Y1/text()")
    return ("./test/Y2/text()")
  ELSE
    //something went wrong, both mytagA and mytagB missing
  END IF
END IF

Open in new window


Of course, I don't ask for error control (the 'ELSE' is just part of the example).

I am only looking to retrieve X1 and X2 values if mytagA is present, otherwise the Y1 and Y2 values.
Thank you in advance for the help..
Gertone (Geert Bormans)Information Architect
Top Expert 2006
Commented:
Have you tried the XPath I sent?

Context I mean, how big is the document, where are the nodes located, what is your starting context for the XPath....

The XPath I sent is very inefficient on large documents, because that XPath scans the entire document 8 times (likely optimised by the processor)

It works as follows
- the if is added as a predicate to the nodes
- the else if is added as a predicate to the alternative nodes
all are joined together with a union, only the nodes that do exist are retained in the result, so this is the XPath way of dealing with the conditions

your pseudo code is different from the original question
try this for the pseudo code example

//X1[//mytagA] | //X2[//mytagA] | //Y1[//mytagB] | //Y2[//mytagB]
this is just testing the presence of the nodes, you can do smarter things such as testing the text value inside the nodes
Announcing the Winners!

The results are in for the 15th Annual Expert Awards! Congratulations to the winners, and thank you to everyone who participated in the nominations. We are so grateful for the valuable contributions experts make on a daily basis. Click to read more about this year’s recipients!

N MConsultant

Author

Commented:
Returning to this question, may I ask for a simplification of your above solution:
How to return the content of mytagA based on the value of X1?

Like: If X1 value = '1000' return X2
(this should return 'MAN' )

I think that will solve the whole problem. (I believe you saw it, because you wrote on last comment "...such as testing the text value inside the nodes" - thank you !!
Gertone (Geert Bormans)Information Architect
Top Expert 2006

Commented:
Three months without a sign of life and instead of a "thank you for your efforts and suggestions" I get a "can you please change this or that?"

I see what I can do when I get home tonight
Information Architect
Top Expert 2006
Commented:
//*[X1 = '1000']/X2

Open in new window


is an implementation of what I explained before
N MConsultant

Author

Commented:
Apologies for the delayed request as well as for not clearly communicated my appreciation - truth is I was trying to put my own effort at work to solve three problems arising from this case. I am definitely much obliged for the time spent on this.

By the way, you solved it. Thanks to your solution I understood how the “union” works and by tackling one tag before the one I need I am now able to read the values.


Many thanks !
N MConsultant

Author

Commented:
Thank you for providing a solution not just to a generic problem but also tweaking the solution so that it can be used in many ways.

Thank you for your substantial support!

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial