6

EclipseLink MOXyを使用してXMLを解析しようとしていますが、xsi属性のある行で失敗しています。これを削除すると、正常に解析されます。ただし、100GiBのXMLを使用する必要があり、ソースファイルを変更することはできません。

設定できればXmlParser.setNamespaceAware(false)機能するはずだと提案されていますが、MOXyの根幹に侵入せずに、これを構成する方法がわかりません。

<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]
4

2 に答える 2

8

現在、EclipseLink JAXB (MOXy)には、名前空間を無視するように指示するオプションはありません。しかし、StAX パーサーを利用して使用できるアプローチがあります。

デモ

名前空間を認識しない XML 入力でStAX を作成XMLStreamReaderし、そこから MOXy を非整列化することができます。

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;
    }

}

入力 (input.xml)

以下は、質問の XML の簡略版です。xsi プレフィックスの名前空間宣言がないため、この XML は適切に名前空間修飾されていないことに注意してください。

<?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>
于 2012-11-16T14:39:38.063 に答える
2

名前空間の認識を完全に無効にするのではなく、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");

次に、アンマーシャラーを作成し、 Blaise's answerxsrのようにアンマーシャリングします。これは明らかに 1 つの特定の StAX 実装に結び付けられますが、既存の JAXB モデル クラスが要素とその子が名前空間にあると想定している場合、それらを変更する必要がないことを意味します。<crossref>http://www.crossref.org/xschema/1.0

于 2012-11-16T15:12:02.457 に答える