JDK-6354990 : REGRESSION: Identity Transform does not demand namespace-prefixes
  • Type: Bug
  • Component: xml
  • Sub-Component: javax.xml.transform
  • Affected Version: 5.0
  • Priority: P3
  • Status: Closed
  • Resolution: Duplicate
  • OS: windows_xp
  • CPU: x86
  • Submitted: 2005-11-23
  • Updated: 2012-04-25
  • Resolved: 2005-12-01
Related Reports
Duplicate :  
Description
FULL PRODUCT VERSION :
java version "1.5.0_01"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_01-b08)
Java HotSpot(TM) Client VM (build 1.5.0_01-b08, mixed mode)


ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows XP [Version 5.1.2600]

A DESCRIPTION OF THE PROBLEM :
The identity transformer created through TransformerFactory.newInstance().newTransformer() does not set the namespace-prefixes feature to true on a SAXSource's XMLReader.

In non-prefix mode it is legal for that XMLReader to report "" as the qname of an element in a namespace. The identity transform will not deal with this and report "" as local name to its target.

1.4.2 (TransformerIdentityImpl:404) would explicitly enable this feature:
reader.setFeature("http://xml.org/sax/features/namespace-prefixes", true);


STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Compile and Run the attached program.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
<?xml version="1.0" encoding="UTF-8"?><html:div xmlns:html="http://w3.org/..."/>

ACTUAL -
<?xml version="1.0" encoding="UTF-8"?>< xmlns="http://w3.org/..." xmlns:html="http://w3.org/..."/>


REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
/*
 * Copyright (c) 2004 CoreMedia AG, Hamburg. All rights reserved.
 */

package test;

import org.xml.sax.*;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.Result;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.sax.SAXSource;
import javax.xml.transform.stream.StreamResult;
import java.io.ByteArrayInputStream;
import java.io.IOException;

/**
 * Wrap an XMLReader and explicitly report "" as qname if prefixes are off.
 */
public class TestXmlReader implements XMLReader {
  private static final String PREFIXES_FEATURE = "http://xml.org/sax/features/namespace-prefixes";

  XMLReader wrapped;
  boolean prefixes = false;

  public TestXmlReader(XMLReader wrapped) {
    this.wrapped = wrapped;
  }

  public boolean getFeature (String name)
      throws SAXNotRecognizedException, SAXNotSupportedException {
    return wrapped.getFeature(name);
  }

  public void setFeature (String name, boolean value)
      throws SAXNotRecognizedException, SAXNotSupportedException {
    if(name.equals(PREFIXES_FEATURE))
      prefixes = value;

    wrapped.setFeature(name, value);
  }

  public Object getProperty (String name)
      throws SAXNotRecognizedException, SAXNotSupportedException {
    return wrapped.getProperty(name);
  }

  public void setProperty (String name, Object value)
      throws SAXNotRecognizedException, SAXNotSupportedException {
    wrapped.setProperty(name, value);
  }

  public void setEntityResolver (EntityResolver resolver) {
    wrapped.setEntityResolver(resolver);
  }

  public EntityResolver getEntityResolver () {
    return wrapped.getEntityResolver();
  }

  public void setDTDHandler (DTDHandler handler) {
    wrapped.setDTDHandler(handler);
  }

  public DTDHandler getDTDHandler () {
    return wrapped.getDTDHandler();
  }

  public void setContentHandler (final ContentHandler handler) {
    wrapped.setContentHandler(new ContentHandler() {
      ContentHandler delegate = handler;

      public void setDocumentLocator (Locator locator) {
	delegate.setDocumentLocator(locator);
      }

      public void startDocument ()
	  throws SAXException {
	delegate.startDocument();
      }

      public void endDocument()
	  throws SAXException {
	delegate.endDocument();
      }

      public void startPrefixMapping (String prefix, String uri)
	  throws SAXException {
	delegate.startPrefixMapping(prefix, uri);
      }

      public void endPrefixMapping (String prefix)
	  throws SAXException {
	delegate.endPrefixMapping(prefix);
      }

      public void startElement (String uri, String localName,
				String qName, Attributes atts)
	  throws SAXException {
	delegate.startElement(uri, localName, prefixes ? qName : "", atts);
      }

      public void endElement (String uri, String localName,
			      String qName)
	  throws SAXException {
	delegate.endElement(uri, localName, prefixes ? qName : "");
      }

      public void characters (char ch[], int start, int length)
	  throws SAXException {
	delegate.characters(ch, start, length);
      }

      public void ignorableWhitespace (char ch[], int start, int length)
	  throws SAXException {
	delegate.ignorableWhitespace(ch, start, length);
      }

      public void processingInstruction (String target, String data)
	  throws SAXException {
	delegate.processingInstruction(target, data);
      }

      public void skippedEntity (String name)
	  throws SAXException {
	delegate.skippedEntity(name);
      }
    });
  }

  public ContentHandler getContentHandler () {
    return wrapped.getContentHandler();
  }

  public void setErrorHandler (ErrorHandler handler) {
    wrapped.setErrorHandler(handler);
  }

  public ErrorHandler getErrorHandler () {
    return wrapped.getErrorHandler();
  }

  public void parse (InputSource input)
      throws IOException, SAXException {
    System.out.println("prefixes are "+(prefixes ? "on" : "off"));
    wrapped.parse(input);
  }

  public void parse (String systemId)
      throws IOException, SAXException {
    System.out.println("prefixes are "+(prefixes ? "on" : "off"));
    wrapped.parse(systemId);
  }

  public static void main(String[] args) throws TransformerException, SAXException, ParserConfigurationException {
    byte[] xml = "<?xml version=\"1.0\"?><html:div xmlns:html=\"http://w3.org/...\"/>".getBytes();

    SAXSource source = new SAXSource(new InputSource(new ByteArrayInputStream(xml)));
    SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
    saxParserFactory.setNamespaceAware(true);

    SAXParser parser = saxParserFactory.newSAXParser();
    source.setXMLReader(new TestXmlReader(parser.getXMLReader()));

    Result result = new StreamResult(System.out);

    TransformerFactory.newInstance().newTransformer().transform(source, result);
  }
}

---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Make the source report qnames even if it's legal to omit them.

Release Regression From : 1.4.2
The above release value was the last known release where this 
bug was known to work. Since then there has been a regression.