Saxon XSLT-Transformation: How to change serializa

2019-09-09 11:11发布

问题:

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">
<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.

回答1:

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.



回答2:

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.



回答3:

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.