1

Need help with XPATH.

I use this library jcabi (see samples) to process XML document. I'm facing a problem (all nodes named "member" are retrived, I just want the first level of "member" nodes not the nested ones.

    XML myXml = new XMLDocument(stringXMLFormat);
    List<XML> members = myXml.xpath("//struct/*"); // the problem is "//stuct/*" I can't find appropriate expression to query only first level of member nodes.

    Instead having members.size() = 4, I have members.size() = 6.
    
    I dont want the two nested member (Member Level 2)
    
    <struct>     +------------------------------------
         <member>| Exclude this part from the result
                 <struct>
                 |     <member>
                 +------------------------------------
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<methodResponse>
    <params>
        <param>
            <value>
                <struct>   <!-- NOT THIS : I apply XPATH query on this :   myXml.xpath("//struct/*") ==> Retrieve all member nodes in the document; but I just want the firs level of member nodes --> 
                    <member> <!-- Member -> Level 1 : Must be retrive --> 
                        <name>attribut1</name>
                        <value>
                            <int>0</int>
                        </value>
                    </member>
                    <member> <!--Member -> Level 1 : Must be retrive --> 
                        <name>attribut2</name>
                        <value>
                            <struct>
                                <member> <!-- Member Level 2 : I don't want to retrive this --> 
                                    <name>attribut2-attr1</name>
                                    <value>
                                        <boolean>1</boolean>
                                    </value>
                                </member>
                            </struct>
                        </value>
                    </member>
                    <member> <!--Member -> Level 1 : Must be retrive --> 
                        <name>attribut3</name>
                        <value>
                            <array>
                                <data>
                                    <value>
                                        <struct> <!--NOT THIS --> 
                                            <member> <!--Member -> Level 2 : I don't want to retrive this --> 
                                                <name>attiribut3-attr-1</name>
                                                <value>
                                                    <int>1</int>
                                                </value>
                                            </member>
                                        </struct>
                                    </value>
                                </data>
                            </array>
                        </value>
                    </member>
                    <member> <!-- Member -> Level 1 : Must be retrive --> 
                        <name>attribut4</name> 
                        <value>
                            <string>10</string>
                        </value>
                    </member>
                </struct>
            </value>
        </param>
    </params>
</methodResponse>

How can I select just the first level of member WITHOUT selected all member in the document ?

Thank you for your help.

1
  • Please let me know if my solution resolved your problem Commented Jan 20, 2022 at 22:15

2 Answers 2

1

Instead of

"//struct/*"

Use

"//param/value/struct/*"

UPD
Explanations:
You are simply selecting all the elements below struct tagged element while my expression will select all the elements below //param/value/struct.
That means:
Find param element directly followed by value directly followed by struct. Now find all the elements below this node.
This will select only relevant member nodes since there are inner member nodes as well but they are sitting below this nodes sequence: //data/value/struct.
The second solution here given by kjhughes is good as well.

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks @Prophet, It works. But don't understand what it means.
@aristos I have added the explanation
Thank you for that explanation, it's help to understand.
0

This XPath,

//member[not(ancestor::member)]

will select all member elements that do not have member element ancestors.

1 Comment

Thanks @kjhughes, it's works. I voted for your answer because you did not only give the correct path but also give the explanation.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.