Как установить namespace aware в false?

Я пытаюсь проанализировать некоторый XML с помощью Eclipselink MOXy, и он терпит неудачу на линии с . Если я удалю это, он отлично разберется. Тем не менее, у меня есть 100GiB XML, чтобы пробраться через и изменение исходных файлов не является вариантом.

было предложено, что если я могу установить XmlParser.setNamespaceAware(false) тогда он должен работать - но я понятия не имею, как настроить это, не врываясь прямо в кишки Мокси.

<record>
<header>
    <!-- citation-id: 14404534; type: journal_article; -->
    <identifier>info:doi/10.1007/s10973-004-0435-2</identifier>
    <datestamp>2009-04-28</datestamp>
    <setSpec>J</setSpec>
    <setSpec>J:1007</setSpec>
    <setSpec>J:1007:2777</setSpec>
</header>
<metadata>
    <crossref xmlns="http://www.crossref.org/xschema/1.0"
        xsi:schemaLocation="http://www.crossref.org/xschema/1.0 http://www.crossref.org/schema/unixref1.0.xsd">
        <journal>
            <journal_metadata language="en">
[...]

исключение, которое я получаю, когда xsi: префикс присутствует:

org.springframework.oxm.UnmarshallingFailureException: JAXB unmarshalling exception; nested exception is javax.xml.bind.UnmarshalException
 - with linked exception:
[Exception [EclipseLink-25004] (Eclipse Persistence Services - 2.4.0.v20120608-r11652): org.eclipse.persistence.exceptions.XMLMarshalException
Exception Description: An error occurred unmarshalling the document
Internal Exception: javax.xml.stream.XMLStreamException: ParseError at [row,col]:[13,107]
Message: http://www.w3.org/TR/1999/REC-xml-names-19990114#AttributePrefixUnbound?crossref&xsi:schemaLocation&xsi]

2 ответов


в настоящее время нет опции в EclipseLink JAXB (MOXy) чтобы сказать ему, чтобы игнорировать пространства имен. Но есть подход, который вы можете использовать, используя парсер StAX.

демо

вы можете создать StAX XMLStreamReader на входе XML, который не знает пространства имен, а затем имеет MOXy unmarshal от этого.

package forum13416681;

import javax.xml.bind.*;
import javax.xml.stream.*;
import javax.xml.transform.stream.StreamSource;

public class Demo {

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

        XMLInputFactory xif = XMLInputFactory.newFactory();
        xif.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, false);
        StreamSource source = new StreamSource("src/forum13416681/input.xml");
        XMLStreamReader xsr = xif.createXMLStreamReader(source);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        Foo root = (Foo) unmarshaller.unmarshal(xsr);

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(root, System.out);
    }

}

Модель Java (Foo)

package forum13416681;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Foo {

    private String bar;

    public String getBar() {
        return bar;
    }

    public void setBar(String bar) {
        this.bar = bar;
    }

}

вход (вход.в XML)

Ниже приведена упрощенная версия XML из вашего вопроса. Обратите внимание, что этот XML не является должным образом пространство имен, так как отсутствует объявление пространства имен для префикса xsi.

<?xml version="1.0" encoding="UTF-8"?>
<foo xsi:schemaLocation="http://www.crossref.org/xschema/1.0 http://www.crossref.org/schema/unixref1.0.xsd">
    <bar>Hello World</bar>
</foo>

выход

Ниже приведен вывод из запуска демонстрационного кода.

<?xml version="1.0" encoding="UTF-8"?>
<foo>
   <bar>Hello World</bar>
</foo>

вместо того, чтобы полностью отключать осведомленность о пространстве имен, вы можете использовать механизм Stax-реализации для объявления xsi префикс заранее, затем синтаксический анализ с включенными пространствами имен. Например, с Woodstox вы можете сказать:

import javax.xml.bind.*;
import javax.xml.stream.*;
import javax.xml.transform.stream.StreamSource;
import com.ctc.wstx.sr.BasicStreamReader;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance("com.example");

        XMLInputFactory xif = XMLInputFactory.newFactory();
        StreamSource source = new StreamSource("input.xml");
        XMLStreamReader xsr = xif.createXMLStreamReader(source);
        ((BasicStreamReader)xsr).getInputElementStack().addNsBinding(
               "xsi", "http://www.w3.org/2001/XMLSchema-instance");

а затем создать unmarshaller и unmarshal xsr а в ответ Блэза. Хотя это, очевидно, связывает вас с одной конкретной реализацией StAX, это означает, что вам не нужно изменять ваши существующие классы модели JAXB, если они ожидают <crossref> элемент и его дети, чтобы быть в http://www.crossref.org/xschema/1.0 пространство имен.