I figured this out, I think.

To add a default namespace, before the first startElement call, do a
content-handler startPrefixMapping call, passing as arguments:

  the prefix: ""  -- this makes it the "default" prefix
  the uri: whatever uri your using for the default namespace in subsequent calls
to startElement.

The good news is that this approach also works for non-Saxon cases.

-Marshall


On 12/12/2016 10:12 PM, Marshall Schor wrote:
> Hi.
>
> We're using the Jaxp API in Java to get a content handler:
>
> transformerFactory = (SAXTransformerFactory) 
> SAXTransformerFactory.newInstance();
>
> //Get a TransformerHandler object that can process SAX ContentHandler events
> into a Result.
> // The transformation is defined as an identity (or copy) transformation,
> // for example to copy a series of SAX parse events into a DOM tree.
>
> mHandler = transformerFactory.newTransformerHandler(); 
>
> mTransformer = mHandler.getTransformer();
>
> etc.
>
> We write content by calling the contentHandler methods, such as
>
> contentHandler.startElement(aNamespace, localname, qname, attributes)
>
> This code has been working fine for years, using the standard XML SAX support 
> in
> Java.
>
> Recently, Saxon 8 or 9 was introduced into the class path, and the Saxon
> versions of the SAXTransformerFactory and TransformerHandler (Open Declaration
> <eclipse-open:%E2%98%82=uimaj-core/C:%5C/Users%5C/IBM_ADMIN%5C/.m2%5C/repository%5C/net%5C/sf%5C/saxon%5C/Saxon-HE%5C/9.7.0-14%5C/Saxon-HE-9.7.0-14.jar%3Cnet.sf.saxon.jaxp%28IdentityTransformerHandler.class%E2%98%83IdentityTransformerHandler%7EIdentityTransformerHandler%7ELnet.sf.saxon.jaxp.IdentityTransformer;>net
> <eclipse-javadoc:%E2%98%82=uimaj-core/C:%5C/Users%5C/IBM_ADMIN%5C/.m2%5C/repository%5C/net%5C/sf%5C/saxon%5C/Saxon-HE%5C/9.7.0-14%5C/Saxon-HE-9.7.0-14.jar%3Cnet>.sf
> <eclipse-javadoc:%E2%98%82=uimaj-core/C:%5C/Users%5C/IBM_ADMIN%5C/.m2%5C/repository%5C/net%5C/sf%5C/saxon%5C/Saxon-HE%5C/9.7.0-14%5C/Saxon-HE-9.7.0-14.jar%3Cnet.sf>.saxon
> <eclipse-javadoc:%E2%98%82=uimaj-core/C:%5C/Users%5C/IBM_ADMIN%5C/.m2%5C/repository%5C/net%5C/sf%5C/saxon%5C/Saxon-HE%5C/9.7.0-14%5C/Saxon-HE-9.7.0-14.jar%3Cnet.sf.saxon>.jaxp
> <eclipse-javadoc:%E2%98%82=uimaj-core/C:%5C/Users%5C/IBM_ADMIN%5C/.m2%5C/repository%5C/net%5C/sf%5C/saxon%5C/Saxon-HE%5C/9.7.0-14%5C/Saxon-HE-9.7.0-14.jar%3Cnet.sf.saxon.jaxp>.IdentityTransformerHandler
> <eclipse-javadoc:%E2%98%82=uimaj-core/C:%5C/Users%5C/IBM_ADMIN%5C/.m2%5C/repository%5C/net%5C/sf%5C/saxon%5C/Saxon-HE%5C/9.7.0-14%5C/Saxon-HE-9.7.0-14.jar%3Cnet.sf.saxon.jaxp%28IdentityTransformerHandler.class%E2%98%83IdentityTransformerHandler>.IdentityTransformerHandler)
> were used instead. This has caused a difference in output, in which our method
> of getting a default namespace to be written, has stopped working with the 
> Saxon
> version.
>
> We are trying to serialize out a form containing start elements, lets say a, 
> b,
> and c,
> **all of which belong to some namespace**,
> let's call it "a-url-to-use-as-default-name-space". 
>
> Our calls to the startElement API pass the namespace string, the element name,
> the element name (again, without any namespace prefix) and attributes (if 
> any).
>
> As a special case, the topmost startElement API call has an attribute added to
> the set of attributes with the attribute name "xmlns", and a value of
> "a-url-to-use-as-default-name-space".  This previously resulted in the 
> generated
> XML something like this:
>
> <a xmlns="a-url-to-use-as-default-name-space">
>     <b ... />     
>     <c ... />
> </a>
>
> When Saxon is used, we've found that it strips off the attribute
> 'xmlns="a-url-to-use-as-default-name-space"'.  I can even see the code snippet
> that does this, when I single-stepped through the code; it's this bit, in
> "ReceivingContentHandler":
>
> public void startElement(String uri, String localname, String rawname,
> Attributes atts)
>             throws SAXException {
>         try {
>             flush(true);
>
>             NodeName elementName = getNodeName(uri, localname, rawname);
>             receiver.startElement(elementName, Untyped.getInstance(),
> localLocator, ReceiverOptions.NAMESPACE_OK);
>
>             for (int n = 0; n < namespacesUsed; n++) {
>                 receiver.namespace(namespaces[n], 0);
>             }
>
>             for (int a = 0; a < atts.getLength(); a++) {
>                 int properties = ReceiverOptions.NAMESPACE_OK;
>                 String qname = atts.getQName(a);
>                 if (qname.startsWith("xmlns") && (qname.length()==5 ||
> qname.charAt(5)==':')) {
>                     // We normally configure the parser so that it doesn't
> notify namespaces as attributes.
>                     // But when running as a TransformerHandler, we have no
> control over the feature settings
>                     // of the sender of the events. So we filter them out, 
> just
> in case. There might be cases
>                     // where we ought not just to ignore them, but to handle
> them as namespace events, but
>                     // we'll cross that bridge when we come to it.
>                     continue;
>                 }
>
> It's the part just above, ending with continue, which discovers we've attached
> an attribute "xmlns", and it skips it.
>
> If this is correct behavior, then I'm guessing there's another way one is
> supposed to use to instruct the Saxon "Identity" XSLT transformer to specify 
> it
> should use a default name space.  Can you please say what that method is?
>
> Thanks.  -Marshall Schor
>

Reply via email to