views:

406

answers:

3

Hello folks!

I do some XSLT-Transformation using Saxon HE 9.2 with the output later being unmarshalled by Castor 1.3.1. The whole thing runs with Java at the JDK 6.

My XSLT-Transformation looks like this:

<xsl:transform
version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:ns="http://my/own/custom/namespace/for/the/target/document"&gt;
<xsl:output method="xml" encoding="UTF-8" indent="no" />
<xsl:template match="/">
  <ns:item>
    <ns:property name="id">
      <xsl:value-of select="/some/complicated/xpath" />
    </ns:property>
    <!-- ... more ... -->
  </ns:item>
</xsl:template>

So the thing is: if the XPath-expression /some/complicated/xpath evaluates to an empty sequence, the Saxon serializer writes <ns:property/> instead of <ns:property></ns:property>. This, however, confuses the Castor unmarshaller, which is next in the pipeline and which unmarshals the output of the transformation to instances of XSD-generated Java-classes.

So my question is: How can I tell the Saxon-serializer to output empty tags not as standalone tags?

Here is what I am proximately currently doing to execute the transformation:

import net.sf.saxon.s9api.*;
import javax.xml.transform.*;
import javax.xml.transform.sax.SAXSource;
// ...

// read data
XMLReader xmlReader = XMLReaderFactory.createXMLReader();
// ... there is some more setting up the xmlReader here ...
InputStream xsltStream = new FileInputStream(xsltFile);
InputStream inputStream = new FileInputStream(inputFile);
Source xsltSource = new SAXSource(xmlReader, new InputSource(xsltStream));
Source inputSource = new SAXSource(xmlReader, new InputSource(inputStream));
XdmNode input = processor.newDocumentBuilder().build(inputSource);

// initialize transformation configuration
Processor processor = new Processor(false);
XsltCompiler compiler = processor.newXsltCompiler();
compiler.setErrorListener(this);
XsltExecutable executable = compiler.compile(xsltSource);
Serializer serializer = new Serializer();
serializer.setOutputProperty(Serializer.Property.METHOD, "xml");
serializer.setOutputProperty(Serializer.Property.INDENT, "no");
serializer.setOutputStream(output);

// execute transformation
XsltTransformer transformer = executable.load();
transformer.setInitialContextNode(input);
transformer.setErrorListener(this);
transformer.setDestination(serializer);
transformer.setSchemaValidationMode(ValidationMode.STRIP);
transformer.transform();

I'd appreciate any hint pointing in the direction of a solution. :-) In case of any unclarity I'd be happy to give more details.

Nightly greetings from Germany, Benjamin

+1  A: 

As far as XML is concerned <x /> and <x></x> are the same thing.

See the XML 1.0 spec about this.

Check your schema to make sure the <ns:property/> is valid for it.

Oded
A: 

If you just want to quickly try, if the standalone tags really cause the problem, you could insert an (empty) comment in the content of <ns:property/> (using <xsl:comment>) - and maybe filter that out later.

Chris Lercher
A: 

Try setting the output method to xhtml instead of xml. Saxon will use the XHTML serializer which will render both the start and end tag.

I don't believe it will add anything additional related to XHTML to the output unless you add addition output parameters. There is a section in the XSLT 2.0 spec dedicated to XHTML serialization for reference. I'm not sure how closely Saxon conforms in this area.

Rob Tanzola
The 'xhtml' output method defines the serialization for certain XHTML elements, meaning for elements in the XHTML namespace `http://www.w3.org/1999/xhtml`. For any other elements (meaning for elements in no namespace or in a namespace different from the XHTML namespace) it does not prescribe or enforce a certain serialization format.
Martin Honnen
That's a great point. In the case of the example above, the .NET version of Saxon HE 9.2 (all that I could grab access to at the time) rendered in the non-minimized format for the namespaced attributes, but it may be a use-at-your-own-risk situation.
Rob Tanzola