1

JAXB 2(Oracle / Metro 版本 2.2.7,我也怀疑其他版本)似乎不能容忍枚举元素中值周围的空格。

最小的例子如下。xmllintXerces都根据模式验证实例。令人费解的想法是,JAXB 验证不会抱怨,而是在尝试访问该值时返回null 。如何配置它以正确返回值?

更新:我已经尝试关联 anXmlAdapter来修剪字符串,如此处所建议,但结果是一样的。

更新二:这是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>

一个.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()));

该代码在运行时路径上需要 Saxon HE,因为使用的 XSLT 是,我使用了以下ivy依赖项:

<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 实现以及您问题中的文档运行以下代码时,我将枚举值作为输出。

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 回答