Один XSD, два инструмента генерации кода, два пространства имен
У меня есть XSD -файл, из которого я хочу создать классы C# и Java.
Сначала я устанавливаю пространство имен в XSD в соответствии с моим пространством имен C#, в котором находятся мои классы. Генерация (с помощью инструментов Microsoft) работает отлично, а также сериализация работает отлично, и я могу проверить их на XSD - идеально.
Теперь я хочу создать классы Java с JAXB. Проблема в том, что создаваемые классы имеют другую структуру пакета, чем в C#. Поэтому, когда я устанавливаю пространство имен XSD в структуру пакета Java, оно работает нормально. Я могу сериализовать и проверять XML.
Теперь мой вопрос (ы): есть ли способ решить это? (Иметь один XSD для обоих инструментов генерации) Неужели мне не хватает понимания, для чего фактически нужно пространство имен?
Спасибо
Изменить: так как кажется, что есть недоразумение, я добавил пример
XSD: targetNamespace = "http://foo.bar/mySubNs/model"
- C# Modelnamespace: com.foo.mySubNs.model (который соответствует пространству имен XSD) все сгенерированные классы будут иметь одно и то же пространство имен, предоставленное через кодер MS
- Java Modelnamespace: com.foo.myOtherSubNs.model (который отличается от пространства имен XSD), сгенерированные классы будут иметь "пространство имен C#". В результате классы не будут компилироваться.
Если бы я изменил пространство имен во время генерации кода для Java, я могу скомпилировать классы. Все идет нормально. Но я не смогу проверить сгенерированный XML этими java-классами по XSD, так как пространство имен отличается.
Чтобы упорядочить мои объекты в Java, я использую JAXB следующим образом:
ValidationEventCollector validationCollector = new ValidationEventCollector();
SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = schemaFactory.newSchema(new File ("my/schema/location"));
// JAXB_CONTEXT is just an instance of "JAXBContext"
Marshaller marshaller = JAXB_CONTEXT.createMarshaller();
marshaller.setSchema(schema);
marshaller.setEventHandler(validationCollector);
marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
JAXBElement<MyClass> root = new JAXBElement<MyClass> ( new QName(MyClass.class.getPackage().getName(),"MyClass"),MyClass.class, node);
marshaller.marshal(root, new File("output/Path/obj.xml"));
Чтобы собрать классы Java из схемы, я использую задачу xjc в скрипте сборки ant:
<xjc destdir="${dir.src.gen}" removeOldOutput="no" extension="true">
<schema dir="${dir.schema}" includes="${file.schema}"/>
<binding dir="${dir.schema}" includes="*.xjb"/>
<produces dir="${dir.src.gen}" includes="**/*.java"/>
</xjc>
2 ответа
Пространство имен XSD не обязательно должно соответствовать структуре пакета, по крайней мере, в Java. При создании классов с использованием JAXB просто предоставьте пакет, в который вы хотите поместить классы.
Вы должны выбрать, какая модель является основной: XSD, C# или код Java. Как только вы сделаете этот выбор, вы должны позволить двум другим измениться, как они могут. Наилучшим выбором будет сделать вашу XSD эталонной моделью, сгенерировать код на обоих языках с помощью соответствующих инструментов и просто принять результаты.
Вы также можете попытаться выбрать пространство имен XML так, чтобы код на обоих концах был удовлетворительным, но не пытайтесь форсировать что-либо до последней буквы. Это не так, как это должно работать.