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

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?
N MConsultantAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Gertone (Geert Bormans)Information ArchitectCommented:
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 MConsultantAuthor 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 ArchitectCommented:
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
OWASP: Forgery and Phishing

Learn the techniques to avoid forgery and phishing attacks and the types of attacks an application or network may face.

N MConsultantAuthor 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 ArchitectCommented:
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
Gertone (Geert Bormans)Information ArchitectCommented:
//*[X1 = '1000']/X2

Open in new window


is an implementation of what I explained before

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
N MConsultantAuthor 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 MConsultantAuthor 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!
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
XML

From novice to tech pro — start learning today.