Source Writing Transformer
http://xml.apache.org/http://www.apache.org/http://www.w3.org/

Main
User Documentation

Transformers
Overview

Default
XSLT Transformer

Core
Fragment Extractor Transformer
I18n Transformer
Log Transformer
SQL Transformer
Filter Transformer
Read DOM Session Transformer
Write DOM Session Transformer
XInclude Transformer
CInclude Transformer
EncodeURL Transformer
SourceWriting Transformer

Optional
XT Transformer
LDAP Transformer

Source Writing Transformer

Diverts xml from a pipeline, writing it to a Source.

Thankfully, FileSource is no longer the only Source that currently implements WritableSource; there are implementations of WebDAV and Apache Slide WritableSources in the scratchpad. Hopefully further WriteableSource implementations (XMLDB, CVS, Email, SQL, etc.) will be appear in the future.

  • Name : write-source
  • Class: org.apache.cocoon.transformation.SourceWritingTransformer
  • Cacheable: no.

If you have built Cocoon with the ScratchPad included (using: ./build.sh -Dinclude.webapp.libs=yes -Dinclude.scratchpad.libs=yes webapp), there is a set of samples set up, including tests at http://localhost:8080/cocoon/mount/editor/tests and a demonstration editor at http://localhost:8080/cocoon/mount/editor/edit/

NotePlease beware of putting these samples on a public-facing server.

The Tags
					
		<source:write>
			[<source:path/>]
			<source:source/>
			<source:fragment/>
		</source:write>
		
		<source:insert/>
			<source:path/>
			<source:source/>
			<source:fragment/>
			[<source:replace/>]
			[<source:reinsert/>]
		</source:insert>
					
				

In the namespace xmlns:source="http://apache.org/cocoon/source/1.0".

The contents of the <source:fragment/> tag are written to the specified WriteableSource when the document containing it is transformed by SourceWritingTransformer.

Definition
					
 <map:transformer name="write-source" 
    src="org.apache.cocoon.transformation.SourceWritingTransformer">
		<map:parameter name="serializer" value="xml"/>  
 </map:transformer/>
					
				

The SourceWritingTransformer is predefined for you in the main SiteMap.

Invocation

This invokes the SourceWritingTransformer on your pipeline.

					
 <map:transform type="write-source"/>
					
				

Or you can over-ride the default serializer here.

					
 <map:transform type="write-source">
   <map:parameter name="serializer" value="my-special-serializer"/>   
 </map:transform>
					
				
The Tags in detail
source:write

The source:write tag can take optional attributes, create (defaults to 'true') and serializer (defaults to the serializer set up in the definition or invocation of the transformer).

Replaces the entire content of a Source (specified by the <source:source/> tag) with the contents of the <source:fragment/> tag, if @create is 'true', a new asset will be created if one does not already exist.

The <source:source/> and <source:fragment/> tags are required, a <source:path/> tag is optional, if specified, the value is an used as an XPath to generate xml in your Source, inwhich to wrap your content.

source:source

The System ID of the Source to be written to.

eg: <source:source>docs/blah.xml</source:source> or <source:source>context:/blah.xml</source:source> etc.

source:fragment

The XML Fragment to be written.

eg:

							
	<source:fragment><foo>
			<bar id="dogcow"/>
		</foo></source:fragment>
							
						

or

							
	<source:fragment>
		<foo/>
		<bar>
			<dogcow/>
		<bar/>
	</source:fragment>
							
						

etc.

NoteThe second example type, can only be used when the <source:path/> tag has been specified.

source:path

[Optional] XPath to specify how your content is wrapped

eg: <source:path>doc</source:path> - your content is placed inside a <doc/> root tag.

NoteIf this parameter is omitted, your content MUST have only ONE top-level node.

source:insert

The source:insert tag can take optional attributes, create (defaults to 'true') and serializer (defaults to the serializer set up in the definition or invocation of the transformer).

Inserts into a Source (specified by the <source:source/> tag) the contents of the tag <source:fragment/> at the XPath location specified in the <source:path/> tag, if @create is 'true', a new Source will be created if one does not already exist.

The <source:source/>, <source:path/> and <source:fragment/> tags are all required, the <source:replace/> and <source:reinsert/> tags are optional.

source:source

The System ID of the Source to be inserted into.

eg: <source:source>docs/blah.xml</source:source> or <source:source>context:/blah.xml</source:source> etc.

source:fragment

The XML Fragment to be written.

eg:

							
	<source:fragment>
		<foo>
			<bar id="dogcow"/>
		</foo>
	</source:fragment>
							
						

or

							
	<source:fragment>
		<foo/>
		<bar>
			<dogcow/>
		<bar/>
	</source:fragment>
							
						

etc.

source:path

source:replace

[Optional] XPath (from <source:path/>) to select the node that is replaced by your new content

eg: <source:replace>foo/bar/dogcow/@status='cut'</source:replace> (is equivalent to this in XSLT: select="foo[bar/dogcow/@status='cut']"), what gets replaced is the <foo/> which has a <bar/> with a <dogcow status="cut"/> in it.

The overwrite attribute of the parent <source:insert/> is used to check if replacing is allowed. If overwrite is 'true' (the default) the node is replaced. If overwrite is 'false' the node is only inserted if the replace node is found.

source:reinsert

[Optional] The XPath (relative to <source:replace/>) to backup the contents of the overwritten node to.

eg: <source:reinsert>foo/versions</source:reinsert> or <source:reinsert>/doc/versions/foo</source:reinsert>.

If specified and a node is replaced, all children of this replaced node will be reinserted at the given path.

Notes
  • if 'replace' is not specified, your 'fragment' is appended as a child of 'path'.
  • if 'replace' is specified and it exists and 'overwrite' is true, your 'fragment' is inserted in 'path', before 'replace' and then 'replace' is deleted.
  • if 'replace' is specified and it exists and 'overwrite' is false, no action occurs.
  • if 'replace' is specified and it does not exist and 'overwrite' is true, your 'fragment' is appended as a child of 'path'.
  • if 'replace' is specified and it does not exist and 'overwrite' is false, your 'fragment' is appended as a child of 'path'.
  • if 'reinsert' is specified and it does not exist, no action occurs.
Examples
Simple Write
						
 <page>
   ...
   <source:write xmlns:source="http://apache.org/cocoon/source/1.0">
     <source:source>context://doc/editable/my.xml</source:source>      
     <source:fragment><page>
       <title>Hello World</title>
       <content>
         <p>This is my first paragraph.</p>
       </content>
     </page></source:fragment>
   </source:write>
   ...
 </page>
						
					
Insert at end
						
 <page>
   ...
   <source:insert xmlns:source="http://apache.org/cocoon/source/1.0">
     <source:source>context://doc/editable/my.xml</source:source>      
     <source:path>page/content</source:path>      
     <source:fragment>
       <p>This paragraph gets <emp>inserted</emp>.</p>
       <p>With this one, at the end of the content.</p>
     </source:fragment>
   </source:insert>
   ...
 </page>
						
					
Replace
						
 <page>
   ...
   <source:insert xmlns:source="http://apache.org/cocoon/source/1.0">
     <source:source>context://doc/editable/my.xml"</source:source>      
     <source:path>page/content</source:path>      
     <source:replace>p[1]</source:replace>      
     <source:fragment>
       <p>This paragraph <emp>replaces</emp> the first paragraph.</p>
     </source:fragment>
   </source:insert>
   ...
 </page>
						
					
Insert at the beginning
						
 <page>
   ...
   <source:insert>
     <source:source>context://doc/editable/my.xml</source:source>
     <source:path>page</source:path>
     <source:replace>content</source:replace>
     <source:reinsert>content</source:reinsert>
     <source:fragment>
       <content>
         <p>This new paragraph gets inserted <emp>before</emp> the other ones.</p>
       </content>
     </source:fragment>
    <source:insert>
   ...
 </page>
						
					

This sample does not currently work, see the tests in the scratchpad at http://localhost:8080/cocoon/mount/editor/tests.

NoteYou must have built Cocoon with the scratchpad included for this link to work.

Sample of the output of these tags

This is the kind of information that the SourceWritingTransformer outputs to the pipeline, replacing the original source:write and source:insert tags

						
 <page>
   ...
   <sourceResult>
     <action>new|overwritten|none</action>
     <behaviour>write|insert<behaviour>
     <execution>success|failure</execution>
     <serializer>xml</serializer>
     <source>source:specific/path/to/context/doc/editable/my.xml</source>
     <message>a message about what happened</message>
   </sourceResult>
   ...
 </page>
						
					
Known Problems

Namespace handling: namespace declarations are not copied to the Source, resulting in invalid XML.

I cannot get the 'insert before' example working, which uses the <source:reinsert/> tag.

Warning

It is not known how robust this transformer is under even moderate load, especially when it comes to more than one person modifying the same file at the same time.

Copyright © 1999-2002 The Apache Software Foundation. All Rights Reserved.