title: How to get all namespaces and URLs to populate xsi:schemaLocation attribute when marshalling a JAXB model
body: <p>In JAXB output I'm trying to populate the xsi:schemaLocation attribute so it contains complete information for <em>all</em> the namespaces and schemas that were used. I am trying to find a better way than hardcoding it!</p>
  
  <p>We have a XML schema that's spread across about fifty files.  Each file defines a type and has its own namespace.  (Not a smart decision I think, but too late to argue that one.)  XJC happily compiles the whole mess and generates classes.  When the output is marshalled all the 50+ namespaces are properly put on the root element.</p>
  
  <p>The problem is that I've been asked to populate the xsi:schemaLocation attribute with <em>all</em> the namespaces and associated schema sources.  So instead of just one namespace-URL pair ("my.co.schema.v1 <a href="http://my.company.com/schemas/my.co.schema.v1.xsd" rel="nofollow">http://my.company.com/schemas/my.co.schema.v1.xsd</a>"), I will need to put 50+ pairs in there.  Sure I can hardcode it but that's wrong.</p>
  
  <p>I'd like to query JAXB about all the sources it used, but that doesn't seem possible. I'm starting to think I have to use a Xerces grammar pool and read all the schemas in again.  Is that the best option? </p>
  
  <p>I added a SCCE below.  Works fine, but as I mentioned, the xsi:schemaLocation attribute is hardcoded and incomplete.</p>
  
  <p>Please help, thanks in advance.</p>
  
  <pre><code>package my.xml.generator;
  
  import java.io.File;
  
  import javax.xml.bind.JAXBContext;
  import javax.xml.bind.JAXBElement;
  import javax.xml.bind.Marshaller;
  
  import my.schema.ComponentType;
  import my.schema.ObjectFactory;
  import my.schema.ProductType;
  
  /**
   * Builds a JAXB object and serializes to a file.
   * 
   * Many thanks to
   * http://blog.bdoughan.com/2010/12/jaxb-and-marshalunmarshal-schema.html
   */
  public class SimpleXmlBuilder {
  
  public static void main(String[] argv) throws Exception {
      if (argv.length != 1)
          throw new IllegalArgumentException(
                  "Usage: SimpleXmlBuilder output-file-path");
  
      // Create a trivial component
      ObjectFactory objectFactory = new ObjectFactory();
      ProductType product = objectFactory.createProductType();
      product.setDeprecated(true);
      // Wrap in a root element
      JAXBElement&lt;ProductType&gt; rootElement = objectFactory
              .createProduct(product);
  
      // Get JAXB going
      Class&lt;?&gt;[] rootElementClass = { ComponentType.class };
      JAXBContext context = JAXBContext.newInstance(rootElementClass);
      Marshaller marshaller = context.createMarshaller();
      // Leave some whitespace for humans
      marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
      // The critical part of the problem!
      marshaller.setProperty(Marshaller.JAXB_SCHEMA_LOCATION,
              "My.Name.Space.v1" + " "
                      + "http://my.server.com/schemas/My.Name.Space.v1.xsd");
  
      // Write to the named file
      marshaller.marshal(rootElement, new File(argv[0]));
      System.out.println("Wrote generated XML to " + argv[0]);
    }
  
  }
  </code></pre>