JAXB解组不能容忍令牌枚举周围的空格

时间:2013-06-14 17:42:23

标签: java xml jaxb xsd jaxb2

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

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

更新:我已尝试根据建议here关联XmlAdapter来修剪字符串,但结果是一样的。

更新II:这里是the ticket at 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
}

2 个答案:

答案 0 :(得分:2)

当我使用JDK 1.7.0_21-b12中的JAXB实现为Mac运行以下代码时,我将获得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日开始的以下链接获取:

答案 1 :(得分:2)

因为(暂时)我想坚持使用JAXB RI(仅被“RI”部分吸引),最后我在XSLT 2.0转换中使用replace(., '^\s+|\s+$', '', 'm')建议{{3 }}

相关代码部分是:

    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,我使用了以下常春藤依赖项:

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