1

JAXB 2 (Oracle / Metro バージョン 2.2.7 と私は他のものも同様だと思います) は、列挙要素の値の周りの空白を許容していないようです。

最小限の例を次に示します。xmllintXercesの両方が、スキーマに対してインスタンスを検証します。不可解な考えは、値にアクセスしようとすると、JAXB 検証は文句を言わずにnullを返すということです。値を正しく返すように構成するにはどうすればよいですか?

更新:ここXmlAdapterで提案されているように、文字列をトリミングするために を関連付けてみましたが、結果は同じです。

更新 II:そして、これが Metro JAXB Jira のチケットです。

A.xsd

<xs:schema targetNamespace="foo://a" 
           xmlns:xs="http://www.w3.org/2001/XMLSchema" 
           xmlns="foo://a">

   <xs:element name="type" type="Type"/>

   <xs:simpleType name="Type">
     <xs:restriction base="xs:token">
         <xs:enumeration value="Archive"/>
         <xs:enumeration value="Organisation"/>
       </xs:restriction>
   </xs:simpleType>

</xs:schema>

a.xml

<a:type xmlns:a="foo://a" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="foo://a A.xsd"
>Organisation </a:type>

(「組織」の後の空白に注意してください)

コードのアンマーシャリング

public static void main(String args[]) throws Exception {
    SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
    JAXBContext payloadContext = JAXBContext.newInstance("a");
    Unmarshaller unmarshaller = payloadContext.createUnmarshaller();
    unmarshaller.setSchema(schemaFactory.newSchema(new Source[]{new StreamSource(new FileInputStream(new File("A.xsd")))}));
    JAXBElement<?> oUnmarshalled = (JAXBElement<?>) unmarshaller.unmarshal(new File("a.xml"));
    Object o = oUnmarshalled.getValue(); // returns NULL
}
4

2 に答える 2

2

(当分の間)JAXB RIに固執したいので(「RI」部分だけに引き寄せられる)、最終的にはここでreplace(., '^\s+|\s+$', '', 'm')提案されているようにXSLT 2.0変換で使用しました。

関連するコード セクションは次のとおりです。

    Source input = new StreamSource(new File("a.xml"));
    TransformerFactory factory = TransformerFactory.newInstance();
    Transformer wsTrimmer = factory.newTransformer(new StreamSource(new File("transform-trim-all.xslt")));

    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    wsTrimmer.transform(input, new StreamResult(bos));

    JAXBElement<?> oUnmarshalled = (JAXBElement<?>) unmarshaller.unmarshal(new ByteArrayInputStream(bos.toByteArray()));

使用される XSLT が であるため、コードにはランタイム パスに Saxon HE が必要です

<dependency org="net.sf.saxon" name="Saxon-HE" rev="9.4"/>

XSLTは次のとおりです。

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
    <xsl:output method="xml" omit-xml-declaration="no" indent="yes"/>
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="text()">
       <xsl:sequence select="replace(., '^\s+|\s+$', '', 'm')"/>
    </xsl:template>
</xsl:stylesheet>
于 2013-06-15T14:42:40.183 に答える
2

Mac 用の JDK 1.7.0_21-b12 で JAXB 実装を使用して次のコードを実行し、質問のドキュメントを使用すると、enum 値が出力として取得されます。

import javax.xml.XMLConstants;
import javax.xml.bind.*;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.*;

public class Demo {

    public static void main(String args[]) throws Exception {
        StreamSource xsd = new StreamSource("src/forum17114304/A.xsd");
        StreamSource xml = new StreamSource("src/forum17114304/a.xml");

        SchemaFactory schemaFactory = SchemaFactory
                .newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
        Schema schema = schemaFactory.newSchema(xsd);
        schema.newValidator().validate(xml);

        JAXBContext payloadContext = JAXBContext.newInstance("a");
        Unmarshaller unmarshaller = payloadContext.createUnmarshaller();
        unmarshaller.setSchema(schema);
        JAXBElement<?> oUnmarshalled = (JAXBElement<?>) unmarshaller
                .unmarshal(xml);
        Object o = oUnmarshalled.getValue(); // returns ORGANISATION
        System.out.println(o);
    }

}

出力

ORGANISATION

アップデート

このユース ケースでは、 EclipseLink JAXB (MOXy)にバグがあるようです。

このバグは、EclipseLink 2.5.1 および 2.6.0 ストリームで修正されています。夜間ダウンロードは、2013 年 6 月 15 日以降、次のリンクから入手できます。

于 2013-06-14T18:58:16.323 に答える