XML-oriented Programming

In order to demonstrate the viability of the Active Tags technology as a system for XML-oriented Programming, some use cases taken from W3C's XML Processing Model Requirements and Use Cases are implemented.

These use cases are also more elaborate scenarii for the regression testing of the engine, thus those that are implemented here are also part of the global test suite of RefleX.

Some of the following use cases are not implemented, when there is an existing tip, tutorial, or test case that is already involving the use case, or when a feature required in the use case is not availble in RefleX. However, if an adaptation of the test is possible, an equivalent demonstration is performed. The numbering of the sections is those taken from the W3C document.

[TODO[In this release, only few use-cases have been considered ; others will come soon...]]

Report

[tests/xunit/xop/xop-err.xml]

 
Skip
Test name
TestsErrorsFailure
0
Summary of tests of XML-Oriented-Programs
5
(188)
0
(0)
0
(0)
1/55.1 Apply a Sequence of Operations - invalid1700
2/55.1 Apply a Sequence of Operations - malformed1700
3/55.1 Apply a Sequence of Operations - valid3100
4/55.4 Document Aggregation7700
5/55.11 Make Absolute URLs4600

5.1 Apply a Sequence of Operations [use-case-apply-sequence]

Apply a sequence of operations such XInclude, validation, and transformation to a document, aborting if the result or an intermediate stage is not valid.

[tests/xunit/xop/5.1/apply-sequence.xcl]

The script above perform the operations expected. In the test suite, 3 scenarii are using it : the first with a valid XML document, the second with an invalid one, and the latter with a malformed one. The name of the tag-test in the test suite is <test:use-case-apply-sequence>.

5.2 XInclude Processing [use-case-xinclude]

  1. Retrieve a document containing XInclude instructions.
  2. Locate documents to be included.
  3. Perform XInclude inclusion.
  4. Return a single XML document.

This use case is already available in the tests of the XCL module (n°1 and n°2). The XInclude instructions are using XPointer references.

5.3 Parse/Validate/Transform [use-case-parse-validate-transform]

  1. Parse the XML.
  2. Perform XInclude.
  3. Validate with Relax NG, possibly aborting if not valid.
  4. Validate with W3C XML Schema, possibly aborting if not valid.
  5. Transform.

NOT IMPLEMENTED : in this version of RefleX validation after parsing is available only with the Active Schema Language ; however parsing, XInclusion, and transformations are operations available. Please refer to [use-case-apply-sequence] for a similar test case (where validation occurs first, with a DTD).

5.4 Document Aggregation [use-case-document-aggregation]

  1. Locate a collection of documents to aggregate.
  2. Perform aggregation under a new document element.
  3. Return a single XML document.

[tests/xunit/xop/5.4/document-aggregation.xcl]

The script above perform the operations expected. In the test suite, there are only 2 files in the directory, but it would work in the same way if there were thousands of files, as the aggregator document is a SAX document. The name of the tag-test in the test suite is <test:document-aggregation>.

5.5 Single-file Command-line Document Processing [use-case-simple-command-line]

  1. Read a DocBook document.
  2. Validate the document.
  3. Process it with XSLT.
  4. Validate the resulting XHTML.
  5. Save the HTML file using HTML serialization.

This test is the same as [use-case-apply-sequence], except that the input is a DocBook document, and that no XInclusion is performed.

5.6 Multiple-file Command-line Document Generation [use-case-multiple-command-line]

  1. Read a list of source documents.
  2. For each document in the list:
    1. Read the document.
    2. Perform a series of XSLT transformations.
    3. Serialize each result.
  3. Alternatively, aggregate the resulting documents and serialize a single result.

This test is available in the tutorial section (Publication with XSLT), but there is a single XSLT transformation, although it is of course possible to chain several transformations. The third step is shown in [use-case-document-aggregation].

5.7 Extracting MathML [use-case-extract-mathml]

Extract MathML fragments from an XHTML document and render them as images. Employ an SVG renderer for SVG glyphs embedded in the MathML.

NOT IMPLEMENTED : there is not yet an SVG renderer in RefleX. Extracting MathML fragments and SVG fragments can be achieved easily with XPath.

5.8 Style an XML Document in a Browser [use-case-style-browser]

Style an XML document in a browser with one of several different stylesheets without having multiple copies of the document containing different xml-stylesheet directives.

NOT IMPLEMENTED : I don't really understand what is expected here... Perhaps a server-side content negociation ? Apache can supply the right stylesheet to the browser according to various contexts (language, user-agent, referer...).

5.9 Run a Custom Program [use-case-run-program]

Run a program of your own, with some parameters, on an XML file and display the result in a browser.

[tests/xunit/xop/xop.xcl]

Each of the batch scripts of this section are invoked in this test suite. Some of them require to set environment variables.

5.10 XInclude and Sign [use-case-xinclude-dsig]

  1. Process an XML document through XInclude.
  2. Transform the result with XSLT using a fixed transformation.
  3. Digitally sign the result with XML Signatures.

NOT IMPLEMENTED : this version of RefleX doesn't support XML signatures ; it's just a tag to implement !

5.11 Make Absolute URLs [use-case-make-absolute-urls]

  1. Process an XML document through XInclude.
  2. Remove any xml:base attributes anywhere in the resulting document.
  3. Schema validate the document with a fixed schema.
  4. For all elements or attributes whose type is xs:anyURI, resolve the value against the base URI to create an absolute URI. Replace the value in the document with the resulting absolute URI.

This example assumes preservation of infoset ([base URI]) and PSVI ([type definition]) properties from step to step. Also, there is no way to reorder these steps as the schema doesn't accept xml:base attributes but the expansion requires xs:anyURI typed values.

[tests/xunit/xop/5.11/make-absolute-urls.xcl]

The script above absolutize the URLs but it doesn't rely on PSVI : the validation step has been discarded. Instead, it uses a filter that update the URLs when an XPath pattern matches the input. The name of the tag-test in the test suite is <test:make-absolute-urls>.

Tests detail

[doc/tests/xunit/xop/xop.cat]

<cat:catalog
    xmlns:cat="http://ns.inria.org/active-catalog"
    xmlns:exp="http://ns.inria.org/active-tags/exp">
    <cat:resource name="http://reflex.gforge.inria.fr/tests-xop.html" uri="xop.exp"
selector="exp:module"/> </cat:catalog>

[doc/tests/xunit/xop/xop.exp]

<exp:module version="1.0" target="test" exp:enable-prefixes="io sys xcl asl test xunit"
    xmlns:io="http://ns.inria.org/active-tags/io"
    xmlns:sys="http://ns.inria.org/active-tags/sys"
    xmlns:xcl="http://ns.inria.org/active-tags/xcl"
    xmlns:exp="http://ns.inria.org/active-tags/exp"
    xmlns:asl="http://ns.inria.org/active-schema"
    xmlns:test="http://reflex.gforge.inria.fr/tests-xop.html"
    xmlns:xunit="http://reflex.gforge.inria.fr/xunit.html">

    <exp:element name="test:use-case-apply-sequence">
        <xunit:test-case name="report/5.1/apply-sequence-valid"
label="5.1 Apply a Sequence of Operations - valid"> <exp:unmarshal name="test" source="5.1/apply-sequence.xcl"/> <xcl:append referent="{ $sys:env }"> <xcl:item name="input" value="{ io:file( '5.1/valid.xml' ) }"/> <xcl:item name="stylesheet" value="{ io:file( '5.1/stylesheet.xsl' ) }"/> <xcl:item name="output" value="{ io:file( 'output/5.1/valid-out.xml' ) }"/> </xcl:append> <exp:invoke processor="{ $test }"/> <!--check the result--> <xcl:parse source="5.1/valid-out.xml" name="output-expected"/> <xcl:parse source="output/5.1/valid-out.xml" name="result"/> <xunit:assert-node-equals result="{ $output-expected }" expected="{ $result }"/> </xunit:test-case> <xunit:test-case name="report/5.1/apply-sequence-invalid"
label="5.1 Apply a Sequence of Operations - invalid"> <exp:unmarshal name="test" source="5.1/apply-sequence.xcl"/> <xcl:append referent="{ $sys:env }"> <xcl:item name="input" value="{ io:file( '5.1/invalid.xml' ) }"/> <xcl:item name="stylesheet" value="{ io:file( '5.1/stylesheet.xsl' ) }"/> <xcl:item name="output" value="{ io:file( 'output/5.1/invalid-out.xml' ) }"/> </xcl:append> <exp:invoke processor="{ $test }"/> <!--check the error--> <xcl:parse source="5.1/invalid-error.xml" name="output-expected"/> <xcl:parse source="{ $sys:ERR }" name="result"/> <xunit:assert-node-equals result="{ $output-expected }" expected="{ $result }"/> </xunit:test-case> <xunit:test-case name="report/5.1/apply-sequence-malformed"
label="5.1 Apply a Sequence of Operations - malformed"> <exp:unmarshal name="test" source="5.1/apply-sequence.xcl"/> <xcl:append referent="{ $sys:env }"> <xcl:item name="input" value="{ io:file( '5.1/malformed.xml' ) }"/> <xcl:item name="stylesheet" value="{ io:file( '5.1/stylesheet.xsl' ) }"/> <xcl:item name="output" value="{ io:file( 'output/5.1/malformed-out.xml' ) }"/> </xcl:append> <exp:invoke processor="{ $test }"/> <!--check the error--> <xcl:parse source="5.1/malformed-error.xml" name="output-expected"/> <xcl:parse source="{ $sys:ERR }" name="result"/> <xunit:assert-node-equals result="{ $output-expected }" expected="{ $result }"/> </xunit:test-case> </exp:element> <exp:element name="test:use-case-document-aggregation"> <xunit:test-case name="report/5.4/document-aggregation" label="5.4 Document Aggregation"> <exp:unmarshal name="test" source="5.4/document-aggregation.xcl"/> <xcl:append referent="{ $sys:env }"> <!--in this directory, there are 2 "purchase order" files--> <xcl:item name="input"
value="{ io:file( '../../../tutorial/basic/xslt/web/purchase-orders/' ) }"/> <xcl:item name="output" value="{ io:file( 'output/5.4/document-aggregation-out.xml' ) }"/> </xcl:append> <exp:invoke processor="{ $test }"/> <!--check the result--> <xcl:parse source="5.4/document-aggregation-out.xml" name="output-expected"/> <xcl:parse source="output/5.4/document-aggregation-out.xml" name="result"/> <xunit:assert-node-equals result="{ $output-expected }" expected="{ $result }"/> </xunit:test-case> </exp:element> <exp:element name="test:use-case-make-absolute-urls"> <xunit:test-case name="report/5.11/make-absolute-urls" label="5.11 Make Absolute URLs"> <exp:unmarshal name="test" source="5.11/make-absolute-urls.xcl"/> <xcl:append referent="{ $sys:env }"> <xcl:item name="input" value="{ io:file( '5.11/make-absolute-urls-in.xml' ) }"/> <xcl:item name="output" value="{ io:file( 'output/5.11/make-absolute-urls-out.xml' ) }"/> </xcl:append> <exp:invoke processor="{ $test }"/> <!--check the result--> <xcl:parse source="5.11/make-absolute-urls-out.xml" name="output-expected"/> <xcl:parse source="output/5.11/make-absolute-urls-out.xml" name="result"/> <xunit:assert-node-equals result="{ $output-expected }" expected="{ $result }"/> <!--xcl:fallback> <xcl:echo value="Unable to run &lt;test:use-case-make-absolute-urls&gt; because you are offline."/> </xcl:fallback--> </xunit:test-case> </exp:element> <exp:element name="test:all"> <test:use-case-apply-sequence/> <test:use-case-make-absolute-urls/> <test:use-case-document-aggregation/> <xunit:merge-reports name="Summary of tests of XML-Oriented-Programs "
source="{ io:file( 'report/' ) }" output="{ io:file( 'xop-err.xml' ) }"/> </exp:element> </exp:module>