users@jaxb.java.net

Re: AW: AW: Duplicated namespace declaration from output xml

From: Colin Fleming <colin.mailinglist_at_gmail.com>
Date: Fri, 21 Nov 2008 13:36:00 +0100

In case anyone is interested, I've posted the code we're using below in case
it's useful:

public class JAXBUtil
{

  private JAXBUtil()
  {
  }

  public static void filterNamespaces(ByteArrayInputStream inputStream,
OutputStream outputStream)
      throws SAXException, IOException, TransformerConfigurationException
  {
    // Parsing, removing the uris that haven't been declared
    SAXTransformerFactory factory = (SAXTransformerFactory)
TransformerFactory.newInstance();
    TransformerHandler transformerHandler = factory.newTransformerHandler();
    transformerHandler.setResult(new StreamResult(outputStream));
    transformerHandler.getTransformer().setOutputProperty(OutputKeys.INDENT,
"yes");

transformerHandler.getTransformer().setOutputProperty(OutputKeys.ENCODING,
"utf-8");
    XMLReader xmlReader = XMLReaderFactory.createXMLReader();
    FilterNamespaces filterNamespaces = new
FilterNamespaces(transformerHandler);
    xmlReader.setContentHandler(filterNamespaces);
    xmlReader.parse(new InputSource(inputStream));
  }

  private static class FilterNamespaces extends DefaultHandler
  {

    private static final String SCHEMA_INSTANCE_URI = "
http://www.w3.org/2001/XMLSchema-instance";
    private final ContentHandler nextHandler;

    private final Map<String, String> uriByPrefix = new HashMap<String,
String>();
    private final Map<String, String> prefixByUri = new HashMap<String,
String>();

    private final Set<String> registeredUris = new HashSet<String>();

    private int depth = 0;
    private final List<Set<String>> registeredByDepth = new
ArrayList<Set<String>>();

    private FilterNamespaces(ContentHandler nextHandler)
    {
      this.nextHandler = nextHandler;
    }

    @Override
    public void setDocumentLocator(Locator locator)
    {
      nextHandler.setDocumentLocator(locator);
    }

    @Override
    public void startDocument() throws SAXException
    {
      nextHandler.startDocument();
    }

    @Override
    public void endDocument() throws SAXException
    {
      nextHandler.endDocument();
    }

    @Override
    public void startPrefixMapping(String prefix, String uri) throws
SAXException
    {
      uriByPrefix.put(prefix, uri);
      prefixByUri.put(uri, prefix);
    }

    @Override
    public void endPrefixMapping(String prefix) throws SAXException
    {
      String uri = uriByPrefix.get(prefix);
      uriByPrefix.remove(prefix);
      prefixByUri.remove(uri);
    }

    @Override
    public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException
    {
      registeredByDepth.add(new HashSet<String>());

      registerNamespace(uri);
      for (int i = 0 ; i < attributes.getLength(); i++)
      {
        String attributeUri = attributes.getURI(i);
        registerNamespace(attributeUri);

        if (SCHEMA_INSTANCE_URI.equals(attributeUri) &&
"type".equals(attributes.getLocalName(i)))
        {
          String value = attributes.getValue(i);
          int index = value.indexOf(':');
          if (index != -1)
          {
            String prefix = value.substring(0, index);
            registerNamespace(uriByPrefix.get(prefix));
          }
        }
      }

      nextHandler.startElement(uri, localName, qName, attributes);
      depth++;
    }

    @Override
    public void endElement(String uri, String localName, String qName)
throws SAXException
    {
      nextHandler.endElement(uri, localName, qName);
      depth--;
      Set<String> registered = registeredByDepth.remove(depth);
      for (String namespace : registered)
      {
        nextHandler.endPrefixMapping(prefixByUri.get(namespace));
        registeredUris.remove(namespace);
      }
    }

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

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

    @Override
    public void processingInstruction(String target, String data) throws
SAXException
    {
      nextHandler.processingInstruction(target, data);
    }

    @Override
    public void skippedEntity(String name) throws SAXException
    {
      nextHandler.skippedEntity(name);
    }

    private void registerNamespace(String uri) throws SAXException
    {
      if ((uri.length() > 0) && !registeredUris.contains(uri))
      {
        String prefix = prefixByUri.get(uri);
        nextHandler.startPrefixMapping(prefix, uri);
        registeredUris.add(uri);
        registeredByDepth.get(depth).add(uri);
      }
    }
  }
}