...
A: You create a combined DFDL schema that accepts ANY of the message types, and distinguishes them by the type code.
Caveat: For this to work, the schemas being combined must have target namespaces, and they all must be distinct target namespaces.
Issue:
is a bug (in Daffodil 3.8.0 and prior) which (until fixed) prevents combining from working for schemas with no namespace.
Jira
server ASF JIRA serverId 5aa69414-a9e9-3523-82ec-879b028fb15b key DAFFODIL-2916 Hint: if DFDL schemas follow the style suggestions in DFDL Schema Style Guide, they are much easier to combine/compose together.
Let's assume you have 3 different message types, A, B, and C. Each has a DFDL schema file a.dfdl.xsd, b.dfdl.xsd, and c.dfdl.xsd.
...
Code Block | ||
---|---|---|
| ||
<schema xmlns:a=".... a .... xmlns="http://www.w3.org/2001/XMLSchema" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:a="urn:a" targetNamespace="... a ...urn:a"> <element name="a_msg" type="a:a_msg_type"/> ... plus type definitions </schema> |
...
Code Block | ||
---|---|---|
| ||
<schema xmlns:b="... b... xmlns="http://www.w3.org/2001/XMLSchema" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:b="urn:b" targetNamespace="... b ...urn:b"> <element name="b_msg" type="b:b_msg_type"/> ... plus type definitions </schema> |
...
Code Block | ||
---|---|---|
| ||
<schema xmlns:c="... c... xmlns="http://www.w3.org/2001/XMLSchema" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:c="urn:c" targetNamespace="... c ...urn:c"> <element name="c_msg" type="c:c_msg_type"/> ... plus type definitions </schema> |
...
Code Block | ||
---|---|---|
| ||
<schema targetNamespacexmlns="http://www.w3.org/2001/XMLSchema" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:a="urn:a" xmlns:b="urn:b" xmlns:c="urn:c" xmlns:abc ...="urn:abc" targetNamespace="urn:abc"> <import namespace="... a ...urn:a" schemaLocation="a.dfdl.xsd"/> <import namespace="... b ...urn:b" schemaLocation="b.dfdl.xsd"/> <import namespace="... c ...urn:c" schemaLocation="c.dfdl.xsd"/> <element name="envelope" type="abc:envelopeType"/> <complexType name="envelopeType"> <sequence> <element name="typeCode" type="xs:unsignedInt"/> <choice dfdl:choiceDispatchKey='{ xs:string(typeCode) }'> <element ref="ma:a_msg" dfdl:choiceBranchKey="0" xmlns:m="...a..."/> <element ref="mb:b_msg" dfdl:choiceBranchKey="1" xmlns:m="...b..."/> <element ref="mc:c_msg" dfdl:choiceBranchKey="2" xmlns:m="...c..."/> </choice> </sequence> </complexType> </schema> |
...
Code Block | ||
---|---|---|
| ||
<schema targetNamespacexmlns="http://www.w3.org/2001/XMLSchema" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:a="urn:a" xmlns:b="urn:b" xmlns:c="urn:c" xmlns:abc="urn:abc ..." targetNamespace="urn:abc"> <import namespace="... a ...urn:a" schemaLocation="a.dfdl.xsd"/> <import namespace="... b ...urn:b" schemaLocation="b.dfdl.xsd"/> <import namespace="... c ...urn:c" schemaLocation="c.dfdl.xsd"/> <element name="envelope" type="abc:envelopeType"/> <complexType name="envelopeType"> <sequence> <sequence <sequence dfdl:hiddenGroupRef="abc:h_typeCode"/> <!-- DIFFERENT: Use a HIDDEN GROUP. --> <choice dfdl:choiceDispatchKey='{ xs:string(typeCode) }'> <element ref="ma:a_msg" dfdl:choiceBranchKey="0" xmlns:m="...a..."/> <element ref="mb:b_msg" dfdl:choiceBranchKey="1" xmlns:m="...b..."/> <element ref="mc:c_msg" dfdl:choiceBranchKey="2" xmlns:m="...c..."/> </choice> </sequence> </complexType> <!-- Up to this point, only one line of the schema was different. The one that references the hidden group below. This hidden group at parse time will populate the typeCode element. The trick to keep it from unparsing is this: At unparse time the elements in the hidden group are not part of the infoset, so when unparsing, the unparser will have nothing to go on when it encounters the need to unparse this hidden choice group. Now, dfdl:choiceDispatchKey is only evaluated when parsing, not when unparsing so the unparser has nothing to go on, so will choose the first branch of the choice here, which contains nothing so nothing gets unparsed. --> <group name="h_typeCode"> <choice dfdl:choiceDispatchKey='{ "parse" }'> <sequence dfdl:choiceBranchKey="unparse"> <!-- Don't unparse anything. By default, when unparsing a choice, the first branch is taken --> </sequence> <sequence dfdl:choiceBranchKey="parse"> <element name="typeCode" type="xs:unsignedInt" dfdl:outputValueCalc='{ 0 }'> <!-- And there is this one additional annoying detail: The dfdl:outputValueCalc above is only present to satisfy the Daffodil schema compiler. All elements in hidden groups must have a way to unparse, which means they are defaultable or have a dfdl:outputValueCalc, or it will not schema-compile. Daffodil's compiler is not quite smart enough to realize this element will never be unparsed so the schema compiler insists on having a dfdl:outputValueCalc even though it the property will never be used. --> </element> </sequence> </choice> </group> </schema> |
...