Unmarshaller и схема в JAXB - PullRequest
       1

Unmarshaller и схема в JAXB

4 голосов
/ 18 декабря 2010

У меня есть приложение, которое может сохранять файлы в различных форматах (все они в формате XML).Поэтому я должен решить проблему с определением, в каком формате файл был сохранен.Итак, я вижу 2 решения

  • , разные форматы имеют разные схемы, поэтому я могу определить их по ним.Я настраиваю схемы так, что получаю из здесь

marshaller.setProperty(Marshaller.JAXB_NO_NAMESPACE_SCHEMA_LOCATION, "bla-bla.xsd");

, поэтому я полагаю, что могу получить его, используя unmarshaller.getProperty(Marshaller.JAXB_NO_NAMESPACE_SCHEMA_LOCATION)

но выдает

javax.xml.bind.PropertyException: jaxb.noNamespaceSchemaLocation

и getSchema() возвращают ноль Итак, как я могу получить расположение схемы?

  • Задание разных адаптеров для разных компонентов с использованием метода setAdapter(Class<A> type, A adapter)

Какой способ предпочтительнее?Если сначала, то как я могу получить метку расположения схемы?

upd пример кода предположим, что у нас есть bean

@XmlRootElement
public class Foo{
    String bar;
    public String getBar() {return bar; }
    public void setBar(String bar) {this.bar = bar;}
}

и код, который генерирует схему, сохраняет экземпляры Foo игрузит потом.

public class Test {
    final static String schemaLoc = "fooschema.xsd";


    public static void write(File file, Foo foo, Schema schema) throws Throwable {
        XMLEventWriter xsw = null;
        try{
            JAXBContext context = JAXBContext.newInstance(Foo.class);
            XMLOutputFactory xof = XMLOutputFactory.newInstance();
            OutputStream out = new FileOutputStream(file);
            xsw = xof.createXMLEventWriter(out);
            Marshaller m = context.createMarshaller();
            m.setSchema(schema);    //schema setted
            System.out.println(">>>marchal : " + m.getSchema());    //check it
            m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
            m.setProperty(Marshaller.JAXB_NO_NAMESPACE_SCHEMA_LOCATION, schemaLoc);
            m.marshal(foo, xsw);
        } finally{
             xsw.close();
        }
    }

    public static Foo load(File file) throws Throwable {
        JAXBContext context = JAXBContext.newInstance(Foo.class);
        Unmarshaller unmarshaller = context.createUnmarshaller();


        System.out.println("unmarshaller schema:" + unmarshaller.getSchema());  //I need get it here
    //  System.out.println("schema_prop:" + unmarshaller.getProperty(Marshaller.JAXB_NO_NAMESPACE_SCHEMA_LOCATION));

        InputStreamReader in = new InputStreamReader(new FileInputStream(file));
        XMLEventReader xer = XMLInputFactory.newInstance()
                .createXMLEventReader(in);
        return Foo.class.cast(unmarshaller.unmarshal(xer));
    }

    private static File createSchema(String schemaLocation) throws Throwable{
        final File target = new File(schemaLocation);
        if(!target.exists()){
            JAXBContext jaxbContext = JAXBContext.newInstance(Foo.class);
            SchemaOutputResolver sor = new SchemaOutputResolver() {
                public Result createOutput(String namespaceURI, String suggestedFileName)
                throws IOException {
                    StreamResult result = new StreamResult(target);
                    result.setSystemId(target.toURI().toURL().toString());
                    return result;
                }
            };
            jaxbContext.generateSchema(sor);
        }
        return target;
    }

    public static void main(String[] args) throws Throwable {
        createSchema(schemaLoc);
        File file = new File("temp.xml");
        Foo foo = new Foo();
        foo.setBar("test bar");
        SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
        Schema schema = factory.newSchema(createSchema(schemaLoc));
        write(file, foo, schema);
        System.out.println("result " + load(file).getBar());
    }

}

схема, которая генерирует

      <xs:element name="foo" type="foo"/>

      <xs:complexType name="foo">
        <xs:sequence>
          <xs:element name="bar" type="xs:string" minOccurs="0"/>
        </xs:sequence>
      </xs:complexType>
    </xs:schema>

наш временный файл

<?xml version="1.0"?>
<foo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="fooschema.xsd">
<bar>test bar</bar></foo>

Как мы видим, существует

xsi:noNamespaceSchemaLocation = "fooschema.xsd"

Как я могу получить этот текст, используя JAXB?

Ответы [ 2 ]

4 голосов
/ 20 декабря 2010

Я бы использовал парсер StAX для получения этой информации (см. Пример ниже).Создайте XMLStreamReader на входе.Продвиньте XMLStreamReader к корневому элементу, используя метод nextTag () .Затем возьмите атрибут noNamespaceSchemaLocation корневого элемента.Затем передайте XMLStreamReader методу unmarshal (XMLStreamReader) в Unmarshaller.

import java.io.FileInputStream;
import javax.xml.XMLConstants;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamReader;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext context = JAXBContext.newInstance(Categories.class);

        XMLInputFactory xif = XMLInputFactory.newInstance();
        FileInputStream fis = new FileInputStream("input.xml");
        XMLStreamReader xsr = xif.createXMLStreamReader(fis);
        xsr.nextTag();
        String noNamespaceSchemaLocation = xsr.getAttributeValue(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "noNamespaceSchemaLocation");
        System.out.println(noNamespaceSchemaLocation);

        Unmarshaller um = context.createUnmarshaller();
        Categories response = (Categories) um.unmarshal(xsr);
    }
}
2 голосов
/ 18 декабря 2010

Вы должны указать местоположение вашей схемы, используя файл, наш справочник fileoutputstream:

http://download.oracle.com/javase/6/docs/api/javax/xml/bind/Marshaller.html

EDIT:

Извините, после прочтения вам действительно нужно местоположение схемы, а не файла XML, и в Интернете есть немало примеров. Большинству из них нравится этот:

http://robaustin.wikidot.com/how-to-improve-perforamance-of-jaxb

Показать, как передать местоположение схемы с помощью загрузчика класса контекста.

EDIT:

По вашим комментариям:

http://download.oracle.com/javase/6/docs/api/javax/xml/bind/Marshaller.html#getSchema%28%29

getSchema () вернет ноль, если схема не установлена ​​на маршаллере. Вот почему вы не можете получить желаемое свойство, потому что оно (схема) не существует.

...