在 JAXB 输出中,我试图填充 xsi:schemaLocation 属性,以便它包含所有使用的名称空间和模式的完整信息。我试图找到一种比硬编码更好的方法!
我们有一个分布在大约 50 个文件中的 XML 模式。每个文件都定义了一个类型并拥有自己的命名空间。(我认为这不是一个明智的决定,但争论这个决定为时已晚。) XJC 愉快地编译整个混乱并生成类。当输出被编组时,所有 50 多个命名空间都被正确地放在根元素上。
问题是我被要求用所有命名空间和关联的模式源填充 xsi:schemaLocation 属性。因此,我需要放置 50 多对,而不是仅仅一对命名空间-URL 对(“my.co.schema.v1 http://my.company.com/schemas/my.co.schema.v1.xsd ”)在那里。当然我可以对其进行硬编码,但这是错误的。
我想向 JAXB 查询它使用的所有来源,但这似乎不可能。我开始认为我必须使用 Xerces 语法池并再次读取所有模式。那是最好的选择吗?
我在下面添加了一个 SCCE。工作正常,但正如我所提到的, xsi:schemaLocation 属性是硬编码且不完整的。
请帮助,提前谢谢。
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<ProductType> rootElement = objectFactory
.createProduct(product);
// Get JAXB going
Class<?>[] 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]);
}
}