XPath Transformation Service

Transforms an XML input using an XPath expression.

Examples

Basic Example

Given a retrieved XML

Input XML

<?xml version="1.0" encoding="UTF-8"?>
<PTZStatus version="2.0" >
    <AbsoluteHigh>
        <elevation>0</elevation>
        <azimuth>450</azimuth>
        <absoluteZoom>10</absoluteZoom>
    </AbsoluteHigh>
</PTZStatus>

The XPath /PTZStatus/AbsoluteHigh/azimuth/text() returns the document

450

Advanced Example

Given a retrieved XML (e.g. from an HIK Vision device with the namespace xmlns="http://www.hikvision.com/ver20/XMLSchema"):

Input XML

<?xml version="1.0" encoding="UTF-8"?>
<PTZStatus version="2.0" xmlns="http://www.hikvision.com/ver20/XMLSchema">
    <AbsoluteHigh>
        <elevation>0</elevation>
        <azimuth>450</azimuth>
        <absoluteZoom>10</absoluteZoom>
    </AbsoluteHigh>
</PTZStatus>

A simple xpath query to fetch the Azimut value does not work as it does not address the namespace.

There are two ways to address the namespace.

  • Simple path which may not work in complex XML.
  • With full qualified path.

The XPath

  • [name()='PTZStatus']/*[name()='AbsoluteHigh']/*[name()='azimuth']/
  • /*[local-name()='PTZStatus' and namespace-uri()='http://www.hikvision.com/ver20/XMLSchema']/*[local-name()='AbsoluteHigh' and namespace-uri()='http://www.hikvision.com/ver20/XMLSchema']/*[local-name()='azimuth' and namespace-uri()='http://www.hikvision.com/ver20/XMLSchema']

returns

<azimuth>450</azimuth>

In Setup

.items

String  Temperature_xml "Temperature [XPATH(/*[name()='PTZStatus']/*[name()='AbsoluteHigh']/*[name()='azimuth']/):%s °C]" {...}
Number  Temperature "Temperature [%.1f °C]"

.rules

rule "Convert XML to Item Type Number"
  when
    Item Temperature_xml changed
  then
    // use the transformation service to retrieve the value
    // Simple
    val mytest = transform("XPATH", "/*[name()='PTZStatus']
                                     /*[name()='AbsoluteHigh']
                                     /*[name()='azimuth']
                                     /text()", 
                                    Temperature_xml.state.toString )  
    // Fully qualified
    val mytest = transform("XPATH", "/*[local-name()='PTZStatus'    and namespace-uri()='http://www.hikvision.com/ver20/XMLSchema']
                                     /*[local-name()='AbsoluteHigh' and namespace-uri()='http://www.hikvision.com/ver20/XMLSchema']
                                     /*[local-name()='azimuth'      and namespace-uri()='http://www.hikvision.com/ver20/XMLSchema']
                                     /text()",
                                    Temperature_xml.state.toString )

    // post the new value to the Number Item
    Temperature.postUpdate( newValue )
end

Now the resulting Number can also be used in the label to change the color or in a rule as value for comparison.

Further Reading