1

I have this XML

<rpc-reply xmlns:junos="http://xml.juniper.net/junos/12.1X46/junos">
    <environment-information xmlns="http://xml.juniper.net/junos/12.1X46/junos-chassis">
        <environment-item>
            <name>Routing Engine</name>
            <class>Temp</class>
            <status>Failed</status>
            <temperature junos:celsius="50">50 degrees C / 122 degrees F</temperature>
        </environment-item>
        <environment-item>
            <name>Routing Engine CPU</name>
            <status>Absent</status>
        </environment-item>
        <environment-item>
            <name>Power Supply 0</name>
            <class>Power</class>
            <status>OK</status>
        </environment-item>
        <environment-item>
            <name>Power Supply 1</name>
            <class>Power</class>
            <status>Absent</status>
        </environment-item>
    </environment-information>
    <cli>
        <banner></banner>
    </cli>
</rpc-reply>

I want to show all "environment-item" that does not have status = "Absent".

I have tried many sites to test XPATH on, but have failed to come up with an answer. The way I figured it would be was /rpc-reply/environment-information/*[not(contains(status, 'Absent'))], or /rpc-reply/environment-information[1]/*[not(contains(status, 'Absent'))] but it's not working.

Two questions:

  1. What's wrong with my XPATH?
  2. Is there a reliable site to test it on? I have gone through the first three pages on google, but since I can't get the XPATH to work on any of them I have a hard time to evaluate them.

Thankful for any explanations. Would rather get a fishing rod than a fish, if I have to choose! :)

Kind regards, Patrik

PatrikJ
  • 2,327
  • 3
  • 24
  • 35

3 Answers3

2

First of all, the XPath tester sites that you tried are probably working perfectly fine.

The reason your expression isn't working is this bit: <environment-information xmlns="http://xml.juniper.net/junos/12.1X46/junos-chassis">

What this means is that <environment-information> and everything under it is in a different namespace and your xpath doesn't reflect that.

There are two ways around this:
1. You can declare namespace bindings in whatever engine you're running the xpath expression in. There is no standard way of doing this, the solution will differ based on the implementation of the engine. Please note that since <rpc-reply> is in the default namespace, you'd have to bind http://xml.juniper.net/junos/12.1X46/junos-chassis to a different prefix and do something like: /rpc-reply/MY_PREFIX:environment-information/*[not(contains(MY_PREFIX:status, 'Absent'))].
2. If your engine supports XPath 2.0 or higher, you can use a namespace wildcard like this: /rpc-reply/*:environment-information/*[not(contains(*:status, 'Absent'))]

biziclop
  • 48,926
  • 12
  • 77
  • 104
  • I should comment too. This saved me SO much head aches and has already paid off. Big thanks for the explanation as well! – PatrikJ Mar 12 '17 at 18:01
1
  1. Look for the status element directly //status/not(text(),'absent') and return the parent element with parent::environment-information
  2. Try a plugin for notepad++ to do this.
LeonG
  • 863
  • 4
  • 11
0

I think this could work:

//*[name()="environment-item" and not(contains(./*[name()="status"], "Absent"))]
eLRuLL
  • 18,488
  • 9
  • 73
  • 99