Hi all,
thanks for the tips.
I ended up creating a new Inputter:
package org.apache.plc4x.sandbox.java.s7.utils
import org.apache.commons.scxml2.Context
import org.apache.daffodil.dpath.NodeInfo
import org.apache.daffodil.japi.infoset.{InfosetInputterProxy,
W3CDOMInfosetInputter}
class W3CDOMTemplateInfosetInputter(document: org.w3c.dom.Document, context:
Context) extends InfosetInputterProxy {
override val infosetInputter = new W3CDOMInfosetInputter(document)
override def getSimpleText(primType: NodeInfo.Kind): String = {
var value = super.getSimpleText(primType)
if(value.startsWith("${") && value.endsWith("}")) {
val varName = value.substring(2, value.length - 1)
val varValue = context.get(varName)
if(varValue.isInstanceOf[String]) {
value = varValue.toString
}
}
value
}
}
With that in my XML I could just add “${variable-name}” like content and output
that instead …
I solved the other way around (Saving things in the context) with simple Xpath
… as I’m not really interested in the XML document itself.
So far my generic Daffodil and SCXML driver seems to be going nicely … really
looking forward to finishing it and doing some benchmarking.
Chris
Von: "Beckerle, Mike" <[email protected]>
Antworten an: "[email protected]" <[email protected]>
Datum: Mittwoch, 30. Januar 2019 um 01:29
An: "[email protected]" <[email protected]>
Betreff: Re: [TDML] Options to ignore values and ordering?
It is possible to assemble a DFDL infoset programmatically.
The InfosetInputters do this in order to feed data from XML into the unparser.
This capability is not exposed for use from an external API for Daffodil like
the JAPI/SAPI modules. The classes are there and can be used.
Take a look at the InfosetInputter class/trait and the XML and JSON flavors of
it and see if it makes sense to you for constructing messages programmatically.
________________________________
From: Christofer Dutz <[email protected]>
Sent: Tuesday, January 29, 2019 2:43:01 PM
To: [email protected]
Subject: Re: [TDML] Options to ignore values and ordering?
Hi Mike,
thanks for that input. However I guess that I don’t even need full
verification. A set of XPath expressions should be enough.
The other direction however I think I could need some help with. Daffodil is
able to serialize XML representations of my format.
However is there a way to not have an XML literal in the end but some mechanism
that allows me to provide variable values?
I was thinking of something like this?
<state id="sendCotpConnectionRequest">
<onentry>
<plc4x:send>
<s7:tpktMessage>
<magicByte>3</magicByte>
<reserved>0</reserved>
<length>18</length>
<userData>
<headerLength>17</headerLength>
<type>224</type>
<CotpTpduConnectionRequest>
<destinationReference>1</destinationReference>
<!-- Insert the value for "cotp-local-reference" as short here -->
<sourceReference><plc4x:insert type="s7:short"
name="cotp-local-reference"/></sourceReference>
<protocolClass>0</protocolClass>
<parameters>
<parameter>
<type>193</type>
<parameterLength>2</parameterLength>
<CotpParameterCallingTsap>
<tsapId><plc4x:insert type="s7:short"
name="cotp-calling-tsap"/></tsapId>
</CotpParameterCallingTsap>
</parameter>
<parameter>
<type>194</type>
<parameterLength>2</parameterLength>
<CotpParameterCalledTsap>
<tsapId><plc4x:insert type="s7:short"
name="cotp-called-tsap"/></tsapId>
</CotpParameterCalledTsap>
</parameter>
<parameter>
<type>192</type>
<parameterLength>1</parameterLength>
<CotpParameterTpduSize>
<tpduSize><plc4x:insert type="s7:byte"
name="cotp-tpdu-size"/></tpduSize>
</CotpParameterTpduSize>
</parameter>
</parameters>
</CotpTpduConnectionRequest>
</userData>
</s7:tpktMessage>
</plc4x:send>
</onentry>
<transition target="receiveCotpConnectionResponse"/>
</state>
Would there be some way to extend Daffodil to do something likte that?
Chris
Von: "Beckerle, Mike" <[email protected]>
Antworten an: "[email protected]" <[email protected]>
Datum: Dienstag, 29. Januar 2019 um 15:49
An: "[email protected]" <[email protected]>
Betreff: Re: [TDML] Options to ignore values and ordering?
I think you are going to have to write a special XML comparison tool.
The unordered issue is usually handled by cannonicalization - i.e., sort things
first, then verify the result of the sort against your expected data.
You can use the XML comparison tool we wrote for the Daffodil TDML runner as a
starting point for yours if you want.
Look in XMLUtils.scala in daffodil-lib.
The usual trick with such comparison tools is getting out useful diagnostic
info for when items are NOT equal, and not stopping at the first little
inequality, but somehow "resynchronizing" back to the subsequent parts of the
data that are still the same, so you can continue comparing more of the
structure. This is not always possible (nor required for your use case perhaps)
but is one of the bigger challenges.
I really recommend this approach of building a test rig like your own
specialized TDML that exactly lets you express the tests you want, does the
kind of comparison you want, etc. This was one of the really good decisions we
made early on in Daffodil development and has paid off very well.
These kinds of comparison tools are very easy to write in Scala using its XML
support. Some people in the scala community are suggesting switching to
different XML libraries, but I have not found a need for that, and Daffodil
makes very heavy use of the original scala.xml library.
________________________________
From: Christofer Dutz <[email protected]>
Sent: Tuesday, January 29, 2019 7:29:43 AM
To: [email protected]
Subject: [TDML] Options to ignore values and ordering?
Hi all,
I am currently trying to use DFDL, to define the interaction in industrial
protocols with DFDL and SCXML (Other thread).
Now I am defining in my SCXML document message content being sent via DFDL.
However when defining the receiving part I would need something I could imagine
is part of TDML.
In my case a response can contain a number of parameters. Each parameter having
different payload. However the order of these is not pre-defined. I would like
to do something like this:
<state id="receiveCotpConnectionResponse">
<onentry>
<plc4x:receive timeout="5000">
<s7:tpktMessage>
<magicByte>3</magicByte>
<reserved>0</reserved>
<!-- Just ignore the content of this field, we don't care about it as
it's only required for parsing. -->
<length><plc4x:ignore/></length>
<userData>
<!-- Just ignore the content of this field, we don't care about it as
it's only required for parsing. -->
<headerLength><plc4x:ignore/></headerLength>
<type>208</type>
<CotpTpduConnectionResponse>
<!-- Make sure the reply uses the same reference as we used in the
request. -->
<destinationReference><plc4x:verify type="s7:short"
name="cotp-local-reference"/></destinationReference>
<!-- Extract the reference the remote would like us to use in this
session. -->
<sourceReference><plc4x:extract type="s7:short"
name="cotp-remote-reference"/></sourceReference>
<protocolClass>0</protocolClass>
<parameters>
<!--
These elements might be transferred in alternate order, we just
care about all of them being
transferred.
-->
<plc4x:unordered>
<parameter>
<type>192</type>
<parameterLength>1</parameterLength>
<CotpParameterTpduSize>
<tpduSize><plc4x:extract type="s7:byte"
name="cotp-tpdu-size"/></tpduSize>
</CotpParameterTpduSize>
</parameter>
<parameter>
<type>193</type>
<parameterLength>2</parameterLength>
<CotpParameterCallingTsap>
<tsapId><plc4x:extract type="s7:short"
name="cotp-calling-tsap"/></tsapId>
</CotpParameterCallingTsap>
</parameter>
<parameter>
<type>194</type>
<parameterLength>2</parameterLength>
<CotpParameterCalledTsap>
<tsapId><plc4x:extract type="s7:short"
name="cotp-called-tsap"/></tsapId>
</CotpParameterCalledTsap>
</parameter>
<!-- The remote might be passing other parameters, we'll just
ignore them for now -->
<plc4x:ignore/>
</plc4x:unordered>
</parameters>
</CotpTpduConnectionResponse>
</userData>
</s7:tpktMessage>
</plc4x:receive>
</onentry>
<transition cond="" target="sendS7SetupCommunicationRequest"/>
<transition cond="" target="error"/>
</state>
“s7” is the namespace of my DFDL schema. The default namespace is the namespace
of SCXML. The “plc4x” namespace is sort of my idea what’s missing.
“insert” would insert some value from an internal context into the template,
“extract” would take values from the message and save it in the context,
“verify” would compare the value it reads with one in the context, “ignore”
would just ignore it and it’s content, “unordered” would sort of allow me to
expect a sequence of elements, but not necessarily in that order.
If TDML has any form of way to define such a “plc4x:ignore” or
“plc4x:unordered”, I would really like to use that. At least those are the
elements I could expect to be useful in something like TDML.
Any ideas/suggestions?
Chris