2011-08-25 27 views
8

名前空間なしXML非整列化することができますJAXBは:どのように私は、XMLファイル持って

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<object> 
    <str>the type</str> 
    <bool type="boolean">true</bool>   
</object> 

をそして私は、私はこれを行うことができますどのように

@XmlRootElement(name="object") 
public class Spec { 
    public String str; 
    public Object bool; 

} 

の下クラスのオブジェクトにそれを非整列化したいです?名前空間を指定しない限り(下記参照)、動作しません。

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<object> 
    <str>the type</str> 
    <bool xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xmlns:xs="http://www.w3.org/2001/XMLSchema" 
     xsi:type="xs:boolean">true</bool>   
</object> 

答えて

5

UPDATE

あなたは、これはtypexsi:typeの間で変換する中間層を導入することにより、仕事を得ることができます。以下JAXB非整列化操作のためにこれを行うにはStAXのStreamReaderDelegateの使用例である:

package forum7184526; 

import java.io.FileInputStream; 

import javax.xml.bind.JAXBContext; 
import javax.xml.bind.Unmarshaller; 
import javax.xml.stream.XMLInputFactory; 
import javax.xml.stream.XMLStreamReader; 
import javax.xml.stream.util.StreamReaderDelegate; 

import org.eclipse.persistence.oxm.XMLConstants; 

public class Demo { 

    public static void main(String[] args) throws Exception { 
     XMLInputFactory xif = XMLInputFactory.newFactory(); 
     XMLStreamReader xsr = xif.createXMLStreamReader(new FileInputStream("input.xml")); 
     xsr = new XsiTypeReader(xsr); 

     JAXBContext jc = JAXBContext.newInstance(Spec.class); 
     Unmarshaller unmarshaller = jc.createUnmarshaller(); 
     Spec spec = (Spec) unmarshaller.unmarshal(xsr); 
    } 

    private static class XsiTypeReader extends StreamReaderDelegate { 

     public XsiTypeReader(XMLStreamReader reader) { 
      super(reader); 
     } 

     @Override 
     public String getAttributeNamespace(int arg0) { 
      if("type".equals(getAttributeLocalName(arg0))) { 
       return XMLConstants.SCHEMA_INSTANCE_URL; 
      } 
      return super.getAttributeNamespace(arg0); 
     } 

    } 
} 

xsi:typeは(Javaでキャストに類似)要素の実際のタイプを指定するためのスキーマ機構です。名前空間を削除すると、文書のセマンティクスが変更されます。 EclipseLink JAXB (MOXy)

我々はあなたが@XmlDescriminatorNode@XmlDescrimatorValueを使用してドメインオブジェクトのための独自の継承インジケータを指定することができます。 (!ありがとうブレーズ)ブレーズのコメントに基づいて

+0

感謝。私は名前空間を持つことでうまくいく。しかし、XMLに名前空間を持たせることはできません(devユーザーに直面するため)が、Javaクラスの注釈でその情報を保持することで、jaxbがXMLを解析するときに "type"と認識し、 "aha、 Javaクラス宣言に従って名前空間 'xsi'の "。 "xs:boolean"と同じです。私は何を言っているのか見ていますか?それともまだできないのですか?私たちの開発者のユーザーはこのようなXML宣言を作成し、それらをJavaに非マーシャルする必要があるため、これが必要です。 – Andrey

+0

@Andrey - あなたはこの作業を行うことができます。以下は、非マーシャルのためにできるアプローチです。 –

+0

こんにちは。 "type"属性のネームスペースを削除するとうまくいきました。ありがとうございます。でも、 "xs:boolean"という属性の値の "xs"名前空間宣言を削除するにはどうすればいいですか?私はいくつかのStreamReaderDelegateメソッドをオーバーライドして演奏しましたが、成功しませんでした。 – Andrey

2

と私の研究:我々は現在、データ型プロパティのカスタマイズのこのタイプを提供していません。 ここに私の問題の解決策があります。そのBlaiseに同意するか、より良い方法がありますか?

package forum7184526; 

import java.io.FileInputStream; 

import javax.xml.bind.JAXBContext; 
import javax.xml.bind.Unmarshaller; 
import javax.xml.stream.XMLInputFactory; 
import javax.xml.stream.XMLStreamReader; 
import javax.xml.stream.util.StreamReaderDelegate; 

import org.eclipse.persistence.oxm.XMLConstants; 

public class Demo { 

public static void main(String[] args) throws Exception { 
    XMLInputFactory xif = XMLInputFactory.newFactory(); 
    XMLStreamReader xsr = xif.createXMLStreamReader(new FileInputStream("input.xml")); 
    xsr = new XsiTypeReader(xsr); 

    JAXBContext jc = JAXBContext.newInstance(Spec.class); 
    Unmarshaller unmarshaller = jc.createUnmarshaller(); 
    Spec spec = (Spec) unmarshaller.unmarshal(xsr); 
} 

private static class XsiTypeReader extends StreamReaderDelegate { 

    public XsiTypeReader(XMLStreamReader reader) { 
     super(reader); 
    } 

    @Override 
    public String getAttributeNamespace(int arg0) { 
     if("type".equals(getAttributeLocalName(arg0))) { 
      return "http://www.w3.org/2001/XMLSchema-instance"; 
     } 
     return super.getAttributeNamespace(arg0); 
    } 

    @Override 
    public String getAttributeValue(int arg0) { 
     String n = getAttributeLocalName(arg0); 
     if("type".equals(n)) { 
     String v = super.getAttributeValue(arg0); 
      return "xs:"+ v; 
     } 
     return super.getAttributeValue(arg0); 
    } 
    @Override 
    public NamespaceContext getNamespaceContext() { 
     return new MyNamespaceContext(super.getNamespaceContext()); 
    } 
} 

private static class MyNamespaceContext implements NamespaceContext { 
    public NamespaceContext _context; 
    public MyNamespaceContext(NamespaceContext c){ 
    _context = c; 
    } 

    @Override 
    public Iterator<?> getPrefixes(String namespaceURI) { 
    return _context.getPrefixes(namespaceURI); 
    } 

    @Override 
    public String getPrefix(String namespaceURI) { 
    return _context.getPrefix(namespaceURI); 
    } 

    @Override 
    public String getNamespaceURI(String prefix) { 
    if("xs".equals(prefix)) { 
     return "http://www.w3.org/2001/XMLSchema"; 
    } 
    return _context.getNamespaceURI(prefix); 
    } 
} 
} 
7

簡単な方法は、あなたがすでにあなたが非整列化したいタイプを知っているので、unmarshalByDeclaredTypeを使用するかもしれません。

すでに設定された名前空間を持っていJAXBElementのに渡すので、

Unmarshaller.unmarshal(rootNode, MyType.class); 

を使用することによって、あなたは、XML名前空間宣言をする必要はありません。

XMLインスタンスの名前空間を参照する必要がないので、これも完全に合法です。http://www.w3.org/TR/xmlschema-0/#POを参照してください。多くのクライアントは、そのようにXMLを生成します。

最後に動作させました。スキーマ内のカスタム名前空間は削除する必要があります。ここで働いているサンプルコード:

スキーマ:

<xsd:schema 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
<xsd:element name="customer"> 
    <xsd:complexType> 
     <xsd:sequence minOccurs="1" maxOccurs="1"> 
     <xsd:element name="name" type="xsd:string" minOccurs="1" maxOccurs="1" /> 
     <xsd:element name="phone" type="xsd:string" minOccurs="1" maxOccurs="1" /> 
     </xsd:sequence> 
    </xsd:complexType> 
</xsd:element> 

XML:

<?xml version="1.0" encoding="UTF-8"?> 
<customer> 
    <name>Jane Doe</name> 
    <phone>08154712</phone> 
</customer> 

JAXBコード:あなたの応答、ブレーズため

JAXBContext jc = JAXBContext.newInstance(Customer.class); 
Unmarshaller u = jc.createUnmarshaller(); 
u.setSchema(schemaInputStream); // load your schema from File or any streamsource 
Customer = u.unmarshal(new StreamSource(inputStream), clazz); // pass in your XML as inputStream 
関連する問題