7

私は次のXMLを持っています:

<ns2:Person name="John" age="20" />

そして、XSDから生成されたJAXBオブジェクトPersonにそれをアンマーシャリングしたいと思います。

これは私が実行しているコードです:

JAXBContext context = JAXBContext.newInstance(PersoEntity.class);
Unmarshaller um = context.createUnmarshaller();
StringReader sr = new StringReader(xml);
Person p = (Person)um.unmarshal(sr);

驚いたことに、次の例外が発生します。

javax.xml.bind.UnmarshalException
 - with linked exception:
[org.xml.sax.SAXParseException: The prefix "ns2" for element "ns2:Person" is not bound.]

どうすれば解決できますか?ありがとう

4

2 に答える 2

6

フラグメントの取得

現在XMLフラグメントを取得している方法により、名前空間宣言が失われています。フラグメントns2にはプレフィックスがなくなり、コロンが含まれる要素名が含まれるだけです(ns2:Person)。これにより、名前空間対応のパーサーで問題が発生します。以下の記事は、XMLフラグメントを取得するためのより良いアプローチかもしれません。

ユースケースの処理

持っているXMLフラグメントを使用してXMLFilter、XML要素からプレフィックスを削除するを作成し、JAXBを利用UnmarshallerHandlerしてアンマーシャリングを行うことができます。

デモ

package forum11968399;

import java.io.StringReader;
import javax.xml.bind.*;
import javax.xml.parsers.*;
import org.xml.sax.*;
import org.xml.sax.helpers.XMLFilterImpl;

public class Demo {

    private static final String xml = "<ns2:Person name='John' age='20' />";

    public static void main(String[] args) throws Exception {
        SAXParserFactory spf = SAXParserFactory.newInstance();
        SAXParser sp = spf.newSAXParser();
        XMLReader xmlReader = sp.getXMLReader();
        XMLFilter xmlFilter = new MyXMLFilter(xmlReader);

        JAXBContext context = JAXBContext.newInstance(PersonEntity.class);
        Unmarshaller um = context.createUnmarshaller();
        UnmarshallerHandler unmarshallerHandler = um.getUnmarshallerHandler();
        xmlFilter.setContentHandler(unmarshallerHandler);

        StringReader sr = new StringReader(xml);
        xmlFilter.parse(new InputSource(sr));
        PersonEntity p = (PersonEntity) unmarshallerHandler.getResult();
    }

    private static class MyXMLFilter extends XMLFilterImpl {

        public MyXMLFilter(XMLReader xmlReader) {
            super(xmlReader);
        }

        @Override
        public void startElement(String uri, String localName, String qName,
                Attributes attributes) throws SAXException {
            int colonIndex = qName.indexOf(':');
            if(colonIndex >= 0) {
                qName = qName.substring(colonIndex + 1);
            }
uri = XML_NAMESPACE; //to prevent unknown XML element exception, we have to specify the namespace here
            super.startElement(uri, localName, qName, attributes);
        }

        @Override
        public void endElement(String uri, String localName, String qName)
                throws SAXException {
            int colonIndex = qName.indexOf(':');
            if(colonIndex >= 0) {
                qName = qName.substring(colonIndex + 1);
            }
            super.endElement(uri, localName, qName);
        }

    }

}

PersonEntity

package forum11968399;

import javax.xml.bind.annotation.*;

@XmlRootElement(name="Person")
@XmlAccessorType(XmlAccessType.FIELD)
public class PersonEntity {

    @XmlAttribute
    private String name;

    @XmlAttribute
    private int age;

}
于 2012-08-15T13:58:03.077 に答える
1

最善の策は、名前空間をバインドする別の要素内に目的の要素をネストすることです。何にバインドするかは重要ではありません。解析する有効なXMLドキュメントにするだけです。次に、宣言されたタイプでアンマーシャリングできます

JAXBContext context = JAXBContext.newInstance(Person.class);
Unmarshaller um = context.createUnmarshaller();
String xml = "<ns2:Person name=\"John\" age=\"20\" />";
String xmlWithPrefixMapped = "<ns2:FakeElement xmlns:ns2=\"someuri\">" + xml + "</ns2:FakeElement>";
StringReader sr = new StringReader(xmlWithPrefixMapped);
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(new InputSource(sr));
Node n = (Node) doc.getDocumentElement().getFirstChild();
JAXBElement<Person> personElement = um.unmarshal(n, Person.class);
Person p = personElement.getValue();
于 2012-08-15T11:36:36.153 に答える