1

I have below xml file wherein I want to select hostname,instance name, instance type using XPATH

<root>
<hosts>
    <host id="11">
        <name>ABC</name>
        <instances>
            <instance id="11-1">
                <name>raj</name>
                <type>linux</type>
                <date>2017</date>
            </instance>
            <instance id="11-2">
                <name>raj1</name>
                <type>linux</type>
                <date>2017</date>
            </instance>
        </instances>
    </host>
    <host id="12">
        <name>XYZ</name>
        <instances>
            <instance id="12-1">
                <name>rahul</name>
                <type>solaris</type>
                <date>2017</date>
            </instance>
        </instances>
    </host>
</hosts>
</root>

I have tried below XPATH which is selecting instance name and type but not sure how to print host name along with instance name and type.

//hosts/host/instances/instance/*[self::name or self:: type]/text()

It selects the below result.

    raj
    linux
    raj1
    linux
    rahul
    solaris

However, I want output like below which has host name included

    ABC
    raj
    linux
    raj1
    linux
    XYZ
    rahul
    solaris
2
  • 1
    FYI, // is quite expensive here -- it tells your XPath engine it needs to search for hosts elements anywhere in the tree, instead of only directly under root. In some engines there's an index for that kind of lookup (BaseX comes to mind), but that's by no means a universal feature. Commented Jun 30, 2017 at 11:06
  • (so if efficiency is important to you, consider /root/hosts instead of //hosts). Commented Jun 30, 2017 at 11:16

3 Answers 3

2

The following (using the | operator to combine the sets of elements selected by any of three queries) will do:

  //hosts/host[./instances/instance/name or ./instances/instance/type]/name/text()
| //hosts/host/instances/instance/name/text()
| //hosts/host/instances/instance/type/text()
Sign up to request clarification or add additional context in comments.

Comments

1

If you want to include output for hostname also, try below:

//hosts/host//*[self::name or self:: type]/text()

3 Comments

Hmm. This probably does do what the OP wants, but doesn't do what they specify (which, if read literally, indicates that only the names which are under a host which has either an name or type attached to an instance should be included).
Yep, this could return wrong output in case of type node under host... Otherwise this should be an acceptable solution
I was more concerned with whether the name of a host with no instances should be included -- the way I read the OP they're implying that it shouldn't, though that could well be an unintended consequence of the way they chose to pose the question.
1

You can achieve your desired result by using any one of below solution -

Solution - 1(Full Path) - you can skip root:

/root/hosts/host/name[text()]|/root/hosts/host/instances/instance/*[self::name or self::type]

Solution - 2(Full Path) with separate query for each result:

/root/hosts/host/name[text()] |/root/hosts/host/instances/instance/name[text()]|/root/hosts/host/instances/instance/type[text()]

Solution - 3(Node Path)

//host/name[text()]|//instance/*[self::name | self::type]

Solution - 4(Node Path)

//host/[self::name]|//instance/[self::name | self::type]

Hope above is helpful.

Comments

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.