SourceWritingTransformer

The Source Writing Transformer is very similar to the Cocoon version. It provides a means to divert XML from the pipeline into an external file. It can also add or delete fragments within the file. There are three tags that form the SourceWritingTransformer framework:

Source Writing Namespace

The SourceWritingTransformer tags exist in their own namespace, which is the same as the Cocoon transformer: "http://apache.org/cocoon/source/1.0".

Source Writing Output

The transformer replaces the tags within the document with the results of the operation. The generalised output (identical to Cocoon) is:

<source:sourceResult> <source:action>new|overwritten|none</source:action> <source:behaviour>write|insert<source:behaviour> <source:execution>success|failure</source:execution> <source:serializer>xml</source:serializer> <source:source>Full file name of processed file</source:source> <source:message>a message about what happened</source:message> </source:sourceResult>

Source Write

Source write tags allow the writing of a complete file to a folder. The overall structure is:

<source:write [create="true"]"> <source:source/> [<source:path/>] <source:fragment/> </source:write>

where

Note that there is no serializer attribute that is present in Cocoon. For example the following structure:

<source:write create="true"> <source:source>context://test.xml</source:source> <source:path>/root/AAA</source:path> <source:fragment> <BBB> <CCC name="bob"/> </BBB> </source:fragment> </source:write>

will write the following file (I have added indentation for clarity)

context://test.xml
<?xml version="1.0"?> <root> <AAA> <BBB> <CCC name="bob"/> </BBB> </AAA> </root>
Note
If you omit <source:path> it is important that the XML within <source:fragment> has only a single node, which will become the root node of the written document.

If you do not as in this example:

<source:write create="true"> <source:source>context://configs/test.xml</source:source> <source:path/> <source:fragment> <BBB/> <CCC name="bob"/> </source:fragment> </source:write>

then the following error is returned

<source:sourceResult> <source:action>new</source:action> <source:behaviour>write<source:behaviour> <source:execution>failure</source:execution> <source:serializer>xml</source:serializer> <source:source>/....../configs/test.xml</source:source> <source:message>Problem processing source document in write-source: Fragment must have one root element if no path declared</source:message> </source:sourceResult>

Source Insert

Source insert tags allow the replacement/insertion of tags within a file. The overall structure is:

<source:insert [create="true"]"> <source:source/> <source:path/> <source:fragment/> [<source:replace/>] </source:insert>

where

Note
Note that there is no @serializer attribute that is present in Cocoon. Note also that the Cocoon <source:reinsert> tag is not used — I confess that I did not understand exactly what was required here and so it seemed to be safe to leave it out.

Assume that we have a file that has been created above:

context://test.xml
<?xml version="1.0"?> <root> <AAA> <BBB> <CCC name="bob"/> </BBB> </AAA> </root>

The <source:insert> comes in several flavours:

Case 1 (replace not specified)

<source:insert create="true"> <source:source>context://configs/test.xml</source:source> <source:path>/root/AAA</source:path> <source:fragment> <BBB/> <CCC name="alice"/> </BBB> </source:fragment> </source:insert>

will append the fragment as a child of /root/AAA:

context://test.xml
<?xml version="1.0"?> <root> <AAA> <BBB> <CCC name="bob"/> </BBB> <BBB> <CCC name="alice"/> </BBB> </AAA> </root>

Case 2 (replace specified, node exists, overwrite true)

<source:insert overwrite="true"> <source:source>context://configs/test.xml</source:source> <source:path>/root/AAA</source:path> <source:replace>BBB/CCC[ @name='alice' ]/parent::*</source:replace> <source:fragment> <BBB> <CCC name="carol"/> </BBB> </source:fragment> </source:insert>

will replace the second <BBB> node with the fragment:

context://test.xml
<?xml version="1.0"?> <root> <AAA> <BBB> <CCC name="bob"/> </BBB> <BBB> <CCC name="carol"/> </BBB> </AAA> </root>

Case 3 (replace specified, overwrite false)

<source:insert overwrite="false"> <source:source>context://configs/test.xml</source:source> <source:path>/root/AAA</source:path> <source:replace>BBB/CCC[ @name='alice' ]/parent::*</source:replace> <source:fragment> <BBB> <CCC name="carol"/> </BBB> </source:fragment> </source:insert>

causes no action to be taken.

Case 4 (replace specified, node does not exist, overwrite true or false)

<source:insert> <source:source>context://configs/test.xml</source:source> <source:path>/root/AAA</source:path> <source:replace>BBB/CCC[ @name='oscar' ]/parent::*</source:replace> <source:fragment> <BBB> <CCC name="carol"/> </BBB> </source:fragment> </source:insert>

will replace the second <BBB> node with the fragment:

context://test.xml
<?xml version="1.0"?> <root> <AAA> <BBB> <CCC name="bob"/> </BBB> <BBB> <CCC name="alice"/> </BBB> <BBB> <CCC name="carol"/> </BBB> </AAA> </root>

Source Delete

Source delete tags delete the specified source file. The overall structure is:

<source:delete> <source:source/> </source:delete>

where

For example:

<source:delete> <source:source>context://configs/test.xml</source:source> </source:delete>
Copyright 2006 – 2023 Hugh Field-Richards. All Rights Reserved.