2016-05-23 10 views
5

このようなベンダーが提供するXMLがあります:JAXBと名前空間のないXML

<?xml version="1.0" encoding="utf-8"?> 
<Foo> 
    <Bar>...</Bar> 
    <Bar>...</Bar> 
</Foo> 

注そこにはxmlns="..."宣言がされていない、またベンダーがスキーマを供給んが。これは変更できません。ベンダーは将来このようにXMLを出荷し続けます。それは要素のために使用することができるように、私は、多かれ少なかれ意味のある名前空間(「http://acme.com/schema」)を宣言した

<?xml version="1.0" encoding="utf-8"?> 
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
      targetNamespace="http://acme.com/schema" 
      xmlns:tns="http://acme.com/schema" 
      elementFormDefault="qualified"> 
    <xsd:element name="Foo"> 
     <xsd:complexType> 
      <xsd:sequence> 
       <xsd:element ref="tns:Bar" maxOccurs="unbounded"/> 
      </xsd:sequence> 
     </xsd:complexType> 
    </xsd:element> 
    <xsd:element name="Bar"> 
     ... 
    </xsd:element> 
</xsd:schema> 

注:

JAXBバインディングを生成するために、私はこのようなスキーマを作成しました参考文献などXJCは以下のpackage-info.javaを生成します。

@javax.xml.bind.annotation.XmlSchema(namespace = "http://acme.com/schema", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED) 
package com.acme.schema; 

それから私は、非整列化するXML文書にしてみてください:

JAXBContext jaxb = JAXBContext.newInstance("com.acme.schema"); 
Unmarshaller unmarshaller = jaxb.createUnmarshaller(); 
InputStream is = this.getClass().getClassLoader().getResourceAsStream("test.xml"); 

InputSource source = new InputSource(is); 
Foo foo = (Foo) unmarshaller.unmarshal(source); 

ここで私が得る例外です:JAXBクラスが空でないものを持っていながら、XML要素は、空の名前空間に属しているので、明らかに

javax.xml.bind.UnmarshalException: unexpected element (uri:"", local:"Foo"). Expected elements are <{http://acme.com/schema}Foo>,...> 

、これは起こります。

XML名前空間を(おそらくXML解析中に)偽装する方法があるため、JAXBは要素を認識してそれらを正常にバインドできますか? XML文書はむしろ膨大なものになる可能性があるため、SAX/StAXソリューションはDOMよりも優先されます。

+0

あなたは上XJCによって生成されたクラスを置くことを気にしますか? –

答えて

2

まず、私はこれをすべてお勧めしません。サードパーティのAPIとの統合は、複雑さを増やすことなく、十分複雑です。名前空間を追加するのはどうしてですか?私はあなたがそれから何を得るか分からない。あなたのコードベースを継承する幸運な人を考えてみましょう。彼らは名前空間の追加を見るでしょうが、なぜそれをやっているのか分かりません。

私はさらに一歩進んで、スキーマを完全に避け、注釈付きPOJOを使用することを推奨します。これらの手順はすべて、複雑化やビルドの手順などを追加するだけです。

しかし、これが決定された場合、これはXSL変換の典型的なケースのようです。あなたは、XSLがそれを変換見つけることができますそして、それはJAXBにあなたの転換を配線するのは簡単なことであるようにthis questionとして、簡単に十分な名前空間が追加されます...

private static Foo unmarshalDocument(InputStream xslStream, InputStream xmlStream) throws Exception { 
    StreamSource stylesource = new StreamSource(xslStream); 
    StreamSource inputStream = new StreamSource(xmlStream); 
    Transformer transformer = TransformerFactory.newInstance().newTransformer(stylesource); 
    JAXBResult result = new JAXBResult(context); 
    transformer.transform(inputStream, result); 
    return (Foo) result.getResult(); 
} 
+0

実際、名前空間はまったく必要ではないことが判明しました。 (私は、 'targetNamespace ='、 'xmlns:tns ='属性と 'tns:'接頭辞に触れ、問題は解決しました離れて。 –

+0

XJCとPOJOの比較 - 私はXMLのスニペットを示していますが、実際のドキュメントはもっと複雑です。注釈付きのPOJOを手作業で作ることは、ここでは過度のものとなります。代わりに、NetBeans XMLツールの優れたスキーマデザイナを使用し、最小限のJAXBカスタマイズを適用しました。これはリアルタイムの節約でした。ビルドプロセスは、Maven + [maven-jaxb2-plugin](https://github.com/highsource/maven-jaxb2-plugin)によって駆動されるので、すべての複雑さは隠されています。しかし、XJC生成のクラスで重要な手動のカスタマイズが必要だったため、再生の考え方が拒否された状況を覚えています。 –