site/tutorials/tdmlTutorial.tdml.xml (162 lines of code) (raw):

<?xml version="1.0" encoding="ASCII"?> <?xml-stylesheet type="text/xsl" href="DFDLTutorialStylesheet.xsl"?> <!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> <tdml:testSuite suiteName="A TDML Tutorial" description="Illustration of how to test DFDL schemas, and also how to report a bug using TDML." xmlns:tdml="http://www.ibm.com/xmlns/dfdl/testData" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xml="http://www.w3.org/XML/1998/namespace" xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:ex="http://example.com" xmlns:gpf="http://www.ibm.com/dfdl/GeneralPurposeFormat" xmlns:daf="urn:ogf:dfdl:2013:imp:daffodil.apache.org:2018:ext" xmlns="http://www.w3.org/1999/xhtml" defaultRoundTrip="true"> <tdml:tutorial xml:space="preserve"><p> This file is an example of a self-contained test described in a TDML file. <br /> These are easily run using the Daffodil command line interface (CLI). <br /> A TDML file is actually a test suite of tests, and we include two here. One is a parser test case, the other an unparser test case. <br /> The file root element is tdml:testSuite which contains namespace prefix definitions (several are generally needed), and other important attributes: </p> <dl> <dt>defaultRoundTrip</dt> <dd>by default a parse test will be run "round trip" meaning both a parse and unparse will be done. If false or omitted a parse test will only parse, an unparse test will only unparse, though this may be controlled on a test-by-test basis with the roundTrip attribute of parserTestCase and unparserTestCase elements.</dd> <dt>defaultConfig</dt> <dd>gives the name of a defined configuration, which can bind external variables, or set tunable parameters. This can also be controlled on a test-by-test basis with the config attribute of the parserTestCase and unparserTestCase elements.</dd> </dl> <p> We begin below by defining a DFDL schema directly in our TDML file. <br /> Use defineSchema to include a DFDL schema directly inside the TDML file. You can alternatively put the DFDL schema in a separate file if you prefer. <br /> The target namespace of these named defineSchemas will be http://example.com which is bound to the prefix "ex" above. <br /> Each defineSchema has a name, so that one TDML file can contain tests which reference different DFDL schemas. <br /> To embed a schema inside the TDML you don't include the xs:schema element from the schema file, nor do you need to wrap the top-level DFDL annotation objects with xs:annotation and xs:appinfo. <br /> In other words, inside a defineSchema you can directly put: dfdl:defineFormat, dfdl:defineEscapeSchema, dfdl:format (for the default format), xs:element, xs:simpleType, xs:complexType, xs:group, xs:import, or xs:include. <br /> It is common for a TDML file to contain an embedded schema which includes or imports other DFDL schemas that are in files. <br /> Our embedded DFDL schema begins with a named format definition - notice no surrounding xs:annotation nor xs:appinfo <br /> We reference a useful starting point format definition provided to the DFDL community by IBM. (It is built into the Daffodil software.) </p></tdml:tutorial> <tdml:defineSchema name="s1" elementFormDefault="unqualified"> <xs:include schemaLocation="/org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/> <dfdl:defineFormat name="myDefaults"> <dfdl:format lengthKind="implicit" representation="text" encoding="ASCII" initiator="" terminator="" separator="" ref="gpf:GeneralPurposeFormat" /> </dfdl:defineFormat> <!-- The dfdl:format annotation puts the above format definition into use for tests that use this defined schema. --> <dfdl:format ref="ex:myDefaults" /> <!-- Include the format we reference from myDefaults. IBM provided this nice one as a good starting point. --> <xs:import namespace="http://www.ibm.com/dfdl/GeneralPurposeFormat" schemaLocation="/IBMdefined/GeneralPurposeFormat.xsd" /> <!-- Now imagine we are reporting a bug with date/time functionality, and this element exercises the feature of concern. --> <xs:element name="myTestRoot" type="xs:dateTime" dfdl:calendarPattern="MM.dd.yyyy 'at' HH:mm:ssZZZZZ" dfdl:calendarPatternKind="explicit" dfdl:lengthKind="delimited" dfdl:terminator="%NL;" /> </tdml:defineSchema> <tdml:tutorial xml:space="preserve"> <h1>Parser Test Cases</h1><p> Here is a test case that exercises the above schema. <br /> A single TDML file can contain many test cases like the one below. <br /> You must give the name of the model (aka the schema), that can be the name of a schema defined immediately in this file like above, or a file name. <br /> You must also give the name of the root element that the test will use. <br /> Because the tdml:testSuite element has defaultRoundTrip="true" this "parser" test case will actually test parsing and unparsing, but as it is a parser test case, it begins with parsing the data to an infoset, then unparses it and checks that it gets back the original data. <br /> Except, that it won't get back the exact original data. The Time Zone notation won't be reproduced exactly. What is unparsed is equivalent to the original, but not identical. So this pass requires that we do a second parse pass, and verify that we get the infoset back that we expected. That is, what was unparsed can be reparsed back to the same infoset. So this test specifies the roundTrip="twoPass" attribute which overrides the default behavior of the suite. </p></tdml:tutorial> <tdml:parserTestCase name="dateTimeTest" root="myTestRoot" model="s1" description="Test of date/time. Runs round trip (parse and unparse) because that is the default for this test suite." roundTrip="twoPass"> <tdml:tutorial xml:space="preserve"><p> The data for your test is given by the tdml:document element, which optionally contains tdml:documentPart elements. A tdml:documentPart can be of type "text", "bytes" or "bits". <br /> Notice specifically the use of the CDATA bracketing of the data in the TDML file. This insures that no unintended whitespace gets inserted around your data. <br /> DFDL Character Entities can be used in textual data. (See the %LF; in there), if the attribute 'replaceDFDLEntities', a boolean, is true. <br /> There are ways to do binary data in hexadecimal, and even bit by bit, and even mixtures of text and binary data. <br /> For this example we'll just look at a simple textual data document. </p></tdml:tutorial> <tdml:document> <tdml:documentPart type="text" replaceDFDLEntities="true"><![CDATA[04.02.2013 at 14:00:56 GMT-05:00%LF;]]></tdml:documentPart> </tdml:document> <tdml:tutorial xml:space="preserve"><p> The infoset element gives the expected infoset, expressed as an XML fragment. </p></tdml:tutorial> <tdml:infoset> <tdml:dfdlInfoset><!--Always need this extra tdml:dfdlInfoset element as well --> <!-- Here is our actual expected result, where the date and time is now in XML's cannonical representation for these. --> <ex:myTestRoot>2013-04-02T14:00:56-05:00</ex:myTestRoot> </tdml:dfdlInfoset> </tdml:infoset> <!-- end of the test case --> </tdml:parserTestCase> <tdml:tutorial xml:space="preserve"> <h1>Unparser Test Cases</h1><p> This is how unparser tests work. <br /> Note the use of the roundTrip="false" attribute to override the defaultRoundTrip="true" that was set on the tdml:testSuite element. <br /> So this test will unparse only, and not attempt to use the same schema to parse the data. </p></tdml:tutorial> <tdml:unparserTestCase name="unparseDateTimeTest" root="myTestRoot" model="s1" description="date time issue, unparser" roundTrip="false"> <tdml:tutorial xml:space="preserve"><p> For an unparser test, the incoming data is the infoset element. <br /> The data for your test is what is expected as output of the unparse. <br /> The infoset element gives the expected infoset, expressed as an XML fragment. In an unparser test, it is normally written first, with the data document second. The order doesn't actually matter. </p></tdml:tutorial> <tdml:infoset> <tdml:dfdlInfoset> <ex:myTestRoot>2013-04-02T14:00:56-05:00</ex:myTestRoot> </tdml:dfdlInfoset> </tdml:infoset> <tdml:document> <tdml:documentPart type="text" replaceDFDLEntities="true"><![CDATA[04.02.2013 at 14:00:56-05:00%CR;%LF;]]></tdml:documentPart> </tdml:document> <!-- end of the test case --> </tdml:unparserTestCase> <!-- end of the whole TDML file --> </tdml:testSuite>