2009-07-11 5 views
4

いくつかのコードスニペット。はJAXBを検証しますが、空白は無視されません

jaxbアンマーシャリングを行うJavaコーディング。かなり簡単で、チュートリアルからオンラインでコピーされています。

JAXBContext jc = JAXBContext.newInstance("xmlreadtest"); 
Unmarshaller u = jc.createUnmarshaller(); 

// setting up for validation. 
SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); 
StreamSource schemaSource = new StreamSource(ReadXml.class.getResource("level.xsd").getFile()); 
Schema schema = schemaFactory.newSchema(schemaSource); 
u.setSchema(schema); 

// parsing the xml 
URL url = ReadXml.class.getResource("level.xml"); 
Source sourceRoot = (Source)u.unmarshal(url); 

xmlファイルの問題要素。この要素には無視される空白だけが含まれます。そのひどく公式に示されているように正確にはファイル内で見つかった。

<HashLine _id='FI6' 
ppLine='1' 
origLine='1' 
origFname='level.cpp'> 
</HashLine> 

この要素を記述したxsd要素。

<xs:element name="HashLine"> 
    <xs:complexType> 
    <xs:attribute name="origLine" type="xs:NMTOKEN" use="required" /> 
    <xs:attribute name="origFname" type="xs:string" use="required" /> 
    <xs:attribute name="_id" type="xs:ID" use="required" /> 
    <xs:attribute name="ppLine" type="xs:NMTOKEN" use="required" /> 
    </xs:complexType> 
</xs:element> 

エラーは、私はエラーがその要素から来て確認した

[org.xml.sax.SAXParseException: cvc-complex-type.2.1: Element 'HashLine' must have no character or element information item [children], because the type's content type is empty.] 

です。

検証なしで正常に読み込まれます。しかし、私はアプリケーションに重い変更や追加を行う予定であるため、検証を使用する必要があります。すべてがマーシャリング/アンマーシャリングされていることを確認する必要があります。

xs:string拡張子を持つsimpleContextを含めるようにcomplexTypeを変更すると、これも正常に機能します。しかし、私は、この問題を全部のエンティティから得ています。その中には、たくさんのxsdファイルがたくさんあります。だから、この問題を回避するためには、xs:stringのxmlドキュメントのすべての要素を基にすることはできません。

イベントj2se 6はapache-xercesのSchemaFactoryを使用していますが、xercesの 'ignore-whitespace'機能を受け入れていないようです。 (すなわちschemaFactory.setFeature())

答えて

4

あなたはEventFilterを用いた従来の検証に空の文字ブロックをフィルタリングするためにStAX APIを使用することができます。

class WhitespaceFilter implements EventFilter { 
    @Override 
    public boolean accept(XMLEvent event) { 
    return !(event.isCharacters() && ((Characters) event) 
     .isWhiteSpace()); 
    } 
} 

これはあなたの入力をラップするために使用することができます。

// strip unwanted whitespace 
XMLInputFactory inputFactory = XMLInputFactory.newInstance(); 
XMLEventReader eventReader = inputFactory 
    .createXMLEventReader(ReadXml.class.getResourceAsStream("level.xml")); 
eventReader = inputFactory.createFilteredReader(eventReader, 
    new WhitespaceFilter()); 

// parsing the xml 
Source sourceRoot = (Source) unmarshaller.unmarshal(eventReader); 

//TODO: proper error + stream handling 
2

私は非常に単純なXSLT変換を書いて、問題の原因となっている特定の要素(空の要素のみ)から空のコンテンツを取り除くことを提案します。次に、JAXBを介してデータを渡す前に、TransformerFactory、Transformerなどを使用して処理ステップを実行します。これにより、XSLTトランスフォームを使用してデータが "消去"されます。ソースXMLでJAXB以外の他の構造が見つかった場合は、XSLTに一連のクリーニングロジックを追加できます。

+0

私は、文書がJAXBに優しくないとは思えません。なぜなら、それはバリデーションに優しいものではないからです。特定の要素をターゲットにするほうがよいでしょう。私はあなたがDOM/XPathと似たようなことをすることができると思いますが、それはXSLTを使うほど優雅ではありません。 – McDowell

+0

ええ、私は、宣言的なアプローチは、この場合必須ではないと考えています。 XML文書がスキーマに準拠していない場合は、バリデーターを渡す前に修正する必要があります。 XSLTはそのようなことに優れています。 – skaffman

+0

両方の回答が提供されました。しかし、私はいくつかの素晴らしいサンプルコードが含まれているので、最初に他の答えを試してみました。後で、さまざまな理由でこのソリューションに切り替えました。 – DragonFax

関連する問題