Статьи

Применение пространства имен во время демарша JAXB

Для некоторых XML-схема — это строгий набор правил для структурирования XML-документа. Но для других это общее руководство, чтобы указать, как должен выглядеть XML. Это означает, что иногда люди хотят принять ввод, который по какой-то причине не соответствует схеме XML. В этом примере я продемонстрирую, как это можно сделать, используя SAX XMLFilter .

Модель Java

Ниже приведена модель Java, которая будет использоваться для этого примера.

Клиент

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
package blog.namespace.sax;
 
import javax.xml.bind.annotation.XmlRootElement;
 
@XmlRootElement
public class Customer {
 
    private String name;
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
}

Пакет-инфо

Мы будем использовать аннотацию уровня пакета @XmlSchema, чтобы указать квалификацию пространства имен для нашей модели.

1
2
3
4
5
6
@XmlSchema(
        namespace='http://www.example.com/customer',
        elementFormDefault=XmlNsForm.QUALIFIED)
package blog.namespace.sax;
 
import javax.xml.bind.annotation.*;

XML Input (input.xml)

Несмотря на то, что в наших метаданных указано, что для всех элементов должно быть определено пространство имен (http://www.example.com/customer), наш входной документ не квалифицирован для пространства имен. XMLFilter будет использоваться для добавления пространства имен во время операции unmarshal .

1
2
3
4
<?xml version='1.0' encoding='UTF-8'?>
<customer>
    <name>Jane Doe</name>
</customer>

XMLFilter (NamespaceFilter)

Самый простой способ создать XMLFilter — это расширить XMLFilterImpl . Для нашего варианта использования мы переопределим методы startElement и endElement . В каждом из этих методов мы будем вызывать соответствующий супер-метод, передавая пространство имен по умолчанию в качестве параметра URI.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
package blog.namespace.sax;
 
import org.xml.sax.*;
import org.xml.sax.helpers.XMLFilterImpl;
 
public class NamespaceFilter extends XMLFilterImpl {
 
    private static final String NAMESPACE = 'http://www.example.com/customer';
 
    @Override
    public void endElement(String uri, String localName, String qName)
            throws SAXException {
        super.endElement(NAMESPACE, localName, qName);
    }
 
    @Override
    public void startElement(String uri, String localName, String qName,
            Attributes atts) throws SAXException {
        super.startElement(NAMESPACE, localName, qName, atts);
    }
 
}

демонстрация

В демонстрационном коде ниже мы сделаем SAX-анализ XML-документа. XMLReader будет помещен в наш XMLFilter . Мы будем использовать UnmarshallerHandler от JAXB в качестве ContentHandler . После завершения анализа мы можем запросить UnmarshallerHandler для полученного объекта Customer .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package blog.namespace.sax;
 
import javax.xml.bind.*;
import javax.xml.parsers.*;
import org.xml.sax.*;
 
public class Demo {
 
    public static void main(String[] args) throws Exception {
        // Create the JAXBContext
        JAXBContext jc = JAXBContext.newInstance(Customer.class);
 
        // Create the XMLFilter
        XMLFilter filter = new NamespaceFilter();
 
        // Set the parent XMLReader on the XMLFilter
        SAXParserFactory spf = SAXParserFactory.newInstance();
        SAXParser sp = spf.newSAXParser();
        XMLReader xr = sp.getXMLReader();
        filter.setParent(xr);
 
        // Set UnmarshallerHandler as ContentHandler on XMLFilter
        Unmarshaller unmarshaller = jc.createUnmarshaller();
        UnmarshallerHandler unmarshallerHandler = unmarshaller
                .getUnmarshallerHandler();
        filter.setContentHandler(unmarshallerHandler);
 
        // Parse the XML
        InputSource xml = new InputSource('src/blog/namespace/sax/input.xml');
        filter.parse(xml);
        Customer customer = (Customer) unmarshallerHandler.getResult();
 
        // Marshal the Customer object back to XML
        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(customer, System.out);
    }
 
}

Выход

Ниже приведен результат запуска демонстрационного кода. Обратите внимание, что выходные данные содержат квалификацию пространства имен на основе метаданных.

1
2
3
4
<?xml version='1.0' encoding='UTF-8'?>
    <name>Jane Doe</name>
</customer>

Дальнейшее чтение

Если вам понравился этот пост, то вы также можете быть заинтересованы в:

Ссылка: применение пространства имен во время JAXB Unmarshal от нашего партнера по JCG Блэза Дафана в блоге Java XML & JSON Binding .