使用JAXB进行Xml->Bean的转换时,如何检测Xml中是否存在多余字段?

例如,Xml为:

<BIPType>
    <BIPCode>B00001</BIPCode>
    <BIPCode>B00002</BIPCode>     
    <ActivityCode>A00000</ActivityCode>
    <ActionCode>1</ActionCode>
</BIPType>

Bean为:

@XmlRootElement(name = "BIPType")
public class BipType {

    @XmlElement(name = "BIPCode")
    @NotBlank
    private String bipCode;

    @XmlElement(name = "ActivityCode")
    private String activityCode;

    @XmlElement(name = "ActionCode")
    private String actionCode;
}

虽然Xml中有两个BIPCode字段,但是这时候JAXB是不会报错的,依然会正常把Xml解析为实体类
BipType(bipCode=B00002, activityCode=A00000, actionCode=1)

也就是说,Xml比Bean范围大没关系?请问下是否有相关配置让JAXB在这种时候也抛出异常呢?

阅读 3.2k
1 个回答

老实说,其实在回答这个问题之前,是没怎么玩过JAXB的 (゚Д゚*)ノ,也许实际我对于它的API操作了解程度可能还没有题主高,但是我只是针对题主提出的问题结合源码去思考解决而已,因此即使我下面的答案也请题主自行核实一下

首先不过大致看了一眼介绍,因为就是一个xmljava互转的工具,主要类也就下面几个
image.png

类和接口设计上JAXB非常清晰,涉及题主的问题主要应该就是Umarshaller接口了,看了一下XML->Java例子

image.png

而题主的需求是希望读取的XML时重复属性或者说多余属性能够报错,那换句话说,题主希望XML文件中的结构需要符合一定的规则或者叫定义

既然说XML文件的规则/定义,那我们应该可以自然而然想到XML Shema,因为XML Shema就是对XML文件的结构做出定义和描述的,也就是咱们常见的xsd文件,如果能把JAXBxsd文件关联起来,校验这个问题就很简单了,因为在XML Shema的语法中,是有一个Order指示器的,其中的<all>指示器,就可以完成题主的需求

image.png

而从上面的简单里例子可以看到,我们要对XML->Java做操作,主要依赖Umarshaller接口,因此我们顺理成章的去查看Umarshaller接口的方法,期待找到符合需求的扩展点,众多方法中,setSchema格外引人注目

image.png

读一下方法注释,明显就是我们想要的,这里方法中的Schema对象应该我们需要根据我们定义的xsd文件创建而得
image.png

那我们首先先把xsd文件准备好,由于没有其他限制,简单就可以了,生成一个BipType.xsd(可以随便网上搜,demo很多,我是捡懒从idea里直接根据java文件快捷键生成的)

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xs:schema version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema">

  <xs:element name="BIPType" type="bipType"/>

  <xs:complexType name="bipType">
      <xs:all>
        <xs:element name="ActionCode" type="xs:string" minOccurs="0"/>
        <xs:element name="BIPCode" type="xs:string" minOccurs="0" block=""/>
        <xs:element name="ActivityCode" type="xs:string" minOccurs="0"/>
      </xs:all>
  </xs:complexType>
</xs:schema>

接下来我们再依据xsd文件来创建schame对象

SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = sf.newSchema(new File("你的路径\\BipType.xsd"));

有了schame对象,我们的Unmarshaller接口就需要再调用一次setSchema方法

JAXBContext jc = JAXBContext.newInstance(BipType.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
unmarshaller.setSchema(schema);

这下就差不多了,最后完整代码试一下

public static void main(String[] args) throws SAXException, JAXBException {
        File file = new File("你的路径\\aaa.xml");

        SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
        Schema schema = sf.newSchema(new File("你的路径\\BipType.xsd"));

        JAXBContext jc = JAXBContext.newInstance(BipType.class);
        Unmarshaller unmarshaller = jc.createUnmarshaller();
        unmarshaller.setSchema(schema);

        BipType bipType = (BipType) unmarshaller.unmarshal(file);

    }

此时执行会报错的
image.png

如果注释掉一个<BIPCode>,则执行成功

如果题主对于XML Schema有其他的校验需求,可以只用简单去修改BipType.xsd即可,具体很多用法操作,还是可以去参考w3cschool的XML Schema部分

能想到的就是这些叭,希望能帮到你,拜~(。・∀・)ノ

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题