XSL Transform in a rule

I can’t figure out why my xlst won’t match:

This is the retrieved xml to match:

<?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>

This is my xlst file:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="xml" indent="no" encoding="UTF-8" omit-xml-declaration="yes"  />
   <xsl:template match="/">
      <xsl:value-of select="/PTZStatus/AbsoluteHigh/azimuth" />
   </xsl:template>
</xsl:stylesheet>

Azimuth is the value I want to get…and this is the rule I use:

rule "upd cam"
when
        Item IPC_Ute_OppdaterStatus received command ON
then
        var String ptzUrl = 'http://192.168.1.9/ISAPI/PTZCtrl/channels/1/status'
        var String retVal = sendHttpGetRequest(ptzUrl)
        val String mytest = transform("XSLT", "ipc_azimuth.xslt", retVal.toString)
        logInfo('debug','mytest : ' + mytest )
end

“mytest” never outputs anything, it’s clearly not matching and therefore an empty string… :thinking:
(I’ve searched the forums and tried other examples but still nothing.)

Why not use XPATH?

val String mytest = transform("XPATH", "/PTZStatus/AbsoluteHigh/azimuth", retVal.toString)

If all you are doing is extracting a single value then XSLT is way overkill. You are basically doing Xpath inside the XSLT anyway.

Log out retVal to make sure you are actually retrieving the XML you think you are.

1 Like

Basically you have a namespace problem. if you remove xmlns="http://www.hikvision.com/ver20/XMLSchema" from your xml it works. How to get around such thing is explained here.

1 Like

XPATH seems to be the solution I want then, but it still doesn’t catch it.

Here’s the log (with retVal to confirm the XML output):

2018-02-22 15:55:11.559 [INFO ] [eclipse.smarthome.model.script.debug] - RetVal: <?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>

2018-02-22 15:55:11.573 [INFO ] [eclipse.smarthome.model.script.debug] - mytest:

Rule:

        var String ptzUrl = 'http://192.168.1.9/ISAPI/PTZCtrl/channels/1/status'
        var String retVal = sendHttpGetRequest(ptzUrl)
        logInfo('debug','RetVal: ' + retVal)
        val String mytest = transform("XPATH", "/PTZStatus/AbsoluteHigh/azimuth", retVal.toString)
        logInfo('debug','mytest : ' + mytest )

Works

val testXml ="<PTZStatus version=\"2.0\" ><AbsoluteHigh><elevation>0</elevation><azimuth>450</azimuth><absoluteZoom>10</absoluteZoom></AbsoluteHigh></PTZStatus>"

val mytest = transform("XPATH", "/PTZStatus/AbsoluteHigh/azimuth/text()[1]", testXml.toString)
logInfo('debug','mytest : ' + mytest )

Works not.

val testXml ="<PTZStatus version=\"2.0\" xmlns=\"http://www.hikvision.com/ver20/XMLSchema\" ><AbsoluteHigh><elevation>0</elevation><azimuth>450</azimuth><absoluteZoom>10</absoluteZoom></AbsoluteHigh></PTZStatus>"

val mytest = transform("XPATH", "/PTZStatus/AbsoluteHigh/azimuth/text()[1]", testXml.toString)
logInfo('debug','mytest : ' + mytest )

Still the namespace problem.

The solution is to add the namespace to the header and reference it in each path segment. Second problem you want the text, at least i think so.

XLST

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:h="http://www.hikvision.com/ver20/XMLSchema">
   <xsl:output method="xml" indent="no" encoding="UTF-8" omit-xml-declaration="yes"  />
   <xsl:template match="/">
      <xsl:value-of select="/h:PTZStatus/h:AbsoluteHigh/h:azimuth/text()[1]" />
   </xsl:template>
</xsl:stylesheet>

Test it https://www.freeformatter.com/xsl-transformer.html#ad-output

XPATH
As we can not set the namespace for the xpath like that, we have to take an other approach.

val testXml ="<PTZStatus version=\"2.0\" xmlns=\"http://www.hikvision.com/ver20/XMLSchema\" ><AbsoluteHigh><elevation>0</elevation><azimuth>450</azimuth><absoluteZoom>10</absoluteZoom></AbsoluteHigh></PTZStatus>"
// Easy way
val mytest = transform("XPATH", "/*[name()='PTZStatus']
                                 /*[name()='AbsoluteHigh']
                                 /*[name()='azimuth']
                                 /text()[1]", testXml.toString)  
// Bullet proof
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()[1]", testXml.toString)
logInfo('debug','mytest : ' + mytest )

Hope this helps.

2 Likes

Thank you! works perfectly :grinning:

I really need to learn more on XML parsing…