Xpath filtering error

Hi,

I am trying to use xpath filter to get some data.

./netconf-console --host=10.249.51.213 --port 10040 --user admin --password admin --get -x ‘/current-pm-list/current-pm-entry[pm-resource-instance="/org-openroadm-device:org-openroadm-device/org-openroadm-device:interface[org-openroadm-device:name=“och-1/0/0/E1.1”]"]’

The above command says Xpath error

./netconf-console --host=10.249.51.213 --port 10040 --user admin --password admin --get -x ‘/current-pm-list/current-pm-entry[pm-resource-instance="/org-openroadm-device:org-openroadm-device/org-openroadm-device:interface[org-openroadm-device:name=‘och-1/0/0/E1.1’]"]’

the above command gives empty data

Can someone let me know what I am doing wrong here.

Wow, an xpath expression where a predicate has an xpath expression that has another predicate - on the shell commandline! That’s quite a challenge…

Basically, not considering all the vagaries of quoting in 1) the shell and 2) XPath and 3) XML. Considering 1), what you type in the shell is not what netconf-console actually gets as an argument - you can see the latter by using ‘echo’. Your first attempt:

$ echo '/current-pm-list/current-pm-entry[pm-resource-instance="/org-openroadm-device:org-openroadm-device/org-openroadm-device:interface[org-openroadm-device:name="och-1/0/0/E1.1"]"]'
/current-pm-list/current-pm-entry[pm-resource-instance="/org-openroadm-device:org-openroadm-device/org-openroadm-device:interface[org-openroadm-device:name="och-1/0/0/E1.1"]"]

It should be pretty clear that this isn’t parseable, since you have nested quoted strings using the same quote character. Your second attempt is getting closer, switching the quote character - but:

$ echo '/current-pm-list/current-pm-entry[pm-resource-instance="/org-openroadm-device:org-openroadm-device/org-openroadm-device:interface[org-openroadm-device:name='och-1/0/0/E1.1']"]'
/current-pm-list/current-pm-entry[pm-resource-instance="/org-openroadm-device:org-openroadm-device/org-openroadm-device:interface[org-openroadm-device:name=och-1/0/0/E1.1]"]

Oops, the shell (according to its specification) ate not just the outer single quotes, but the internal ones too - no go. This can be handled by another form of quote character switching:

echo '/current-pm-list/current-pm-entry[pm-resource-instance="/org-openroadm-device:org-openroadm-device/org-openroadm-device:interface[org-openroadm-device:name='"'"och-1/0/0/E1.1"'"']"]'
/current-pm-list/current-pm-entry[pm-resource-instance="/org-openroadm-device:org-openroadm-device/org-openroadm-device:interface[org-openroadm-device:name='och-1/0/0/E1.1']"]

And that should actually be possible for an XPath engine to parse - but you’re still out of luck, because in the XML of the actual <get> RPC, the XPath filter is an attribute (select) of the <filter> parameter - so yes, it needs to be quoted! And we’re out of quote characters… netconf-console (a Python script) applies a pretty simple rule that covers most XPath expressions, but not this one: if the expression has any single quotes it uses double quotes for the attribute value, otherwise single quotes. So it ends up producing something like:

<filter type="xpath"
        select="/current-pm-list/current-pm-entry[pm-resource-instance="/org-openroadm-device:org-openroadm-device/org-openroadm-device:interface[org-openroadm-device:name='och-1/0/0/E1.1']"]"/>

Which of course is again unparseable, in fact it’s not even valid XML. But all is not lost - XML allows you to “escape” the inner double quotes by using an entity:

<filter type="xpath"
        select="/current-pm-list/current-pm-entry[pm-resource-instance=&quot;/org-openroadm-device:org-openroadm-device/org-openroadm-device:interface[org-openroadm-device:name='och-1/0/0/E1.1']&quot;]"/>

I.e. back on your commandline:

$ echo '/current-pm-list/current-pm-entry[pm-resource-instance=&quot;/org-openroadm-device:org-openroadm-device/org-openroadm-device:interface[org-openroadm-device:name='"'"och-1/0/0/E1.1"'"']&quot;]'
/current-pm-list/current-pm-entry[pm-resource-instance=&quot;/org-openroadm-device:org-openroadm-device/org-openroadm-device:interface[org-openroadm-device:name='och-1/0/0/E1.1']&quot;]

I actually think that should work, but not having a data model where it could match anything, I haven’t verified it beyond seeing that I get no error and empty data:

$ netconf-console --get -x '/current-pm-list/current-pm-entry[pm-resource-instance=&quot;/org-openroadm-device:org-openroadm-device/org-openroadm-device:interface[org-openroadm-device:name='"'"och-1/0/0/E1.1"'"']&quot;]'
<?xml version="1.0" encoding="UTF-8"?>
<rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="1">
  <data/>
</rpc-reply>

Of course routinely doing these gymnastics on the commandline isn’t really feasible - if I had a need to do that, I’d probably create a wrapper script that took the two XPath expressions as separate arguments somehow, did the needed massaging, and invoked netconf-console with the result - perhaps also generating the <get> RPC and passing that to netconf-console via the --rpc option.

Hm, you could actually use XML entities to avoid the “shell ate the internal single quotes” problem too - this should also work, and while it is actually 4 characters longer, it might be slightly easier to produce and read:

$ netconf-console --get -x '/current-pm-list/current-pm-entry[pm-resource-instance=&quot;/org-openroadm-device:org-openroadm-device/org-openroadm-device:interface[org-openroadm-device:name=&apos;och-1/0/0/E1.1&apos;]&quot;]'
<?xml version="1.0" encoding="UTF-8"?>
<rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="1">
  <data/>
</rpc-reply>

This works. Thank you very much, :slight_smile: