Hello,
I don't know a lot about XML or XPath, so I was hoping someone could help me out.
I'm trying to parse out 'Event: dialog' state notifications from NOTIFYs using xmlops. They look like this:
<?xml version="1.0"?> <dialog-info xmlns="urn:ietf:params:xml:ns:dialog-info" version="5" state="full" entity="sip:abalashov-roaming@xxx.xxx.xxx.xxx"> <dialog id="0588e460-d293-11e3-8563-538b9e69fee5" direction="initiator"> <state>terminated</state> </dialog> </dialog-info>
So, I do:
$xml(u=>doc) = $rb;
xlog("L_INFO", "State: $xml(u=>xpath:/dialog-info/dialog[1]/state/text())\n");
This produces a blank result. I've tried numerous other variations, such as:
xpath:/dialog-info/dialog/state/text()
None of them work, either. When I upload the above XML body to various online XPath validation tools and try my expressions, they work fine.
Any ideas as to what I'm missing? Do I need to indicate the namespace in the XPath expression somehow? If so, how do I do it?
Thanks!
-- Alex
It's definitely namespace-related, because when I manually hack out the namespace, it works fine!
$var(x) = $rb; $var(x) = $(var(x){re.subst,/xmlns=".+"//});
$xml(u=>doc) = $var(x);
xlog("L_INFO", "State: $xml(u=>xpath:/dialog-info/dialog[1]/state/text())\n");
But I can't for the life of me figure out how to construct an XPath expression that properly captures the urn:ietf:params:xml:ns:dialog-info namespace.
This kind usage of xmlns in an xml doc is a hack done by SIMPLE WG breaking XML standard, because any ns has to use a prefix for each corresponding name. If you search on google, you will fine some discussions on the web (iirc, Inaki was there as well) - libxml2 devs said they don't want to break the xml standard to handle this case, probably they didn't change the mind meanwhile.
Anyhow, set a prefix for the namespace via xml_ns parameter and then use it in xpath
modparam("xmlops", "xml_ns", "di=urn:ietf:params:xml:ns:dialog-info")
$xml(u=>xpath:/di:dialog-info/di:dialog[1]/di:state/text())
Hope i remembered correctly, anyhow it is somewhere in this direction. If not, search on mailing list archive, the situation popped up few times around.
Cheers, Daniel
On 03/05/14 09:49, Alex Balashov wrote:
It's definitely namespace-related, because when I manually hack out the namespace, it works fine!
$var(x) = $rb; $var(x) = $(var(x){re.subst,/xmlns=".+"//});
$xml(u=>doc) = $var(x);
xlog("L_INFO", "State: $xml(u=>xpath:/dialog-info/dialog[1]/state/text())\n");
But I can't for the life of me figure out how to construct an XPath expression that properly captures the urn:ietf:params:xml:ns:dialog-info namespace.
On 05/03/2014 04:31 AM, Daniel-Constantin Mierla wrote:
This kind usage of xmlns in an xml doc is a hack done by SIMPLE WG breaking XML standard, because any ns has to use a prefix for each corresponding name. If you search on google, you will fine some discussions on the web (iirc, Inaki was there as well) - libxml2 devs said they don't want to break the xml standard to handle this case, probably they didn't change the mind meanwhile.
Anyhow, set a prefix for the namespace via xml_ns parameter and then use it in xpath
modparam("xmlops", "xml_ns", "di=urn:ietf:params:xml:ns:dialog-info")
$xml(u=>xpath:/di:dialog-info/di:dialog[1]/di:state/text())
Hope i remembered correctly, anyhow it is somewhere in this direction. If not, search on mailing list archive, the situation popped up few times around.
Thanks Daniel. I was heading in this direction, too, before I got lazy and just hacked out the xmlns attribute with {re.subst}. :-)
On 03/05/14 10:33, Alex Balashov wrote:
On 05/03/2014 04:31 AM, Daniel-Constantin Mierla wrote:
This kind usage of xmlns in an xml doc is a hack done by SIMPLE WG breaking XML standard, because any ns has to use a prefix for each corresponding name. If you search on google, you will fine some discussions on the web (iirc, Inaki was there as well) - libxml2 devs said they don't want to break the xml standard to handle this case, probably they didn't change the mind meanwhile.
Anyhow, set a prefix for the namespace via xml_ns parameter and then use it in xpath
modparam("xmlops", "xml_ns", "di=urn:ietf:params:xml:ns:dialog-info")
$xml(u=>xpath:/di:dialog-info/di:dialog[1]/di:state/text())
Hope i remembered correctly, anyhow it is somewhere in this direction. If not, search on mailing list archive, the situation popped up few times around.
Thanks Daniel. I was heading in this direction, too, before I got lazy and just hacked out the xmlns attribute with {re.subst}. :-)
Probably would be good to add a module parameter to do this change internally, like replacing 'xmlns' with 'xmlnx' - iirc, there is a copy if xml doc in a local buffer and by sticking to same size, there is no overall size change, so just one char replacement.
This could come handy when needing just to read. If one needs to update the xml doc, then the above could break things when generating the new xml.
Cheers, Daniel
On 05/03/2014 04:31 AM, Daniel-Constantin Mierla wrote:
modparam("xmlops", "xml_ns", "di=urn:ietf:params:xml:ns:dialog-info")
$xml(u=>xpath:/di:dialog-info/di:dialog[1]/di:state/text())
This worked, by the way. Thank you!