当前位置: 首页 > 知识库问答 >
问题:

JAXB解组:意外元素

陆斌
2023-03-14

背景:

我使用JAXB将XML解组为Java对象。最初,我只是使用JAXB来执行解组。然后对代码进行静态分析,并提出了XML外部实体注入的高关键性问题。经过一点研究,我发现了一个建议(https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Prevention_Cheat_Sheet#JAXB_Unmarshaller)使用配置为防止解析外部实体的解析器。提供了一个操作示例:

//Disable XXE
SAXParserFactory spf = SAXParserFactory.newInstance();
spf.setFeature("http://xml.org/sax/features/external-general-entities", false);
spf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
spf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);

//Do unmarshall operation
Source xmlSource = new SAXSource(spf.newSAXParser().getXMLReader(), new InputSource(new StringReader(xml)));
JAXBContext jc = JAXBContext.newInstance(Object.class);
Unmarshaller um = jc.createUnmarshaller();
um.unmarshal(xmlSource);

我并没有完全按照图中所示那样做,但我相信我实际上也做了同样的事情:

XMLReader reader = getXMLReader();

if (reader == null) {
  logger.warn("Unable to create XML reader");
  return;
}

JAXBContext context = JAXBContext.newInstance(messageClass);
Unmarshaller unmarshaller = context.createUnmarshaller();

for (File file : files) {
  try {
    InputSource source = new InputSource(new FileReader(file));
    Source xmlSource = new SAXSource(reader, source);
    JAXBElement<? extends BaseType> object =
        (JAXBElement<? extends BaseType>) unmarshaller.unmarshal(xmlSource);
    messages.add(object.getValue());
  } catch (FileNotFoundException e) {
    logger.error("Exception", e);
  }
}

...

private XMLReader getXMLReader() {
    SAXParserFactory factory = SAXParserFactory.newInstance();

    try {
      factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
      factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
      factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
    } catch (SAXNotRecognizedException | SAXNotSupportedException
        | ParserConfigurationException e) {
      logger.error("Exception", e);
    }

    XMLReader reader = null;

    try {
      reader = factory.newSAXParser().getXMLReader();
    } catch (SAXException | ParserConfigurationException e) {
      logger.error("Exception", e);
    }

    return reader;
}

问题:

在实现更正后,当程序尝试读取XML时,我现在收到一个解组异常:

javax.xml.bind.UnmarshalException: unexpected element (uri:"", local:"ns1:TypeXYZ"). Expected elements are <{protected namespace URI}TypeABC>,...<{protected namespace URI}TypeXYZ>,...

在上述修复之前,我只是使用JAXB解组,它能够正确解析提供的XML,没有问题。

我假设SAX解析器希望XML提供缺失的额外信息,或者需要将其配置为忽略它所抱怨的任何信息。我尝试了其他一些“功能”(http://xml.org/sax/features/namespace-prefixes=true和http://xml.org/sax/features/validation=false),但这并没有解决问题。

我无法控制定义XML类型的XML模式,也无法控制如何生成相应的Java类。

如果有任何信息可以帮助我了解正在发生的事情,并帮助我解决这个问题,我们将不胜感激。

共有1个答案

漆雕嘉平
2023-03-14

经过一点实验,我能够通过设置以下功能来解决错误:

factory.setFeature("http://xml.org/sax/features/validation", false);
factory.setFeature("http://xml.org/sax/features/namespaces", true);
factory.setFeature("http://xml.org/sax/features/namespace-prefixes", true);
 类似资料:
  • 为什么在使用JAXB时需要使用? 我的工作场景是这样的: 我正在做一个从.NET到Java的转换项目。在.NET中,类的编写与POJO类似。我只是在代码中添加了注释(如、等)。并解决了与注释相关的错误。 现在我犯了这样的错误: XML文件如下: POJO类:

  • 我尝试解组一个XML文件到一个对象。 我得到了这个错误: 我的解组过程如下所示: 我的XML实体看起来像: 我的XMLFile看起来像: 那么,我的解组过程出了什么问题?XML实体是用xjc创建的。 我也尝试了简单的xml文件/对象。这对我来说很好。

  • Borrower类使用基于XSD的JaxB解析,使用JDK1.7和Eclipse IDE。 : } XSD: XML:

  • 我尝试使用SOAP服务,用maven cxf-codegen-plugin生成存根。大多数服务都很好,除了一个难看的服务。在这种情况下,当被调用时,服务发送一个正确的响应,但是我生成的存根无法解组它,从而生成一个异常,比如(我用一个类似urlx的名称替换了URL,以简化) : javax.xml.ws.soap。SOAPFaultException:解组错误:意外元素(uri:“url3”,loc

  • 当使用NIST CPE的标准CPE 2.3 XML模式定义时,我得到了一个“意外元素”错误。 返回带有此错误的JAXBExcture: 我的问题是:这个错误意味着什么 有什么建议可以解决这个问题吗 笔记: 我使用右键单击通过Eclipse Neon创建了JAXB 解组代码非常简单: 与类似问题不同;我不认为这是元素名的大小写问题,因为元素名“head”根本不出现在任何地方。我不完全理解为什么uri

  • 在使用标准CPE2.3XML模式定义处理NIST CPE时,我收到一个“意外元素”错误。 返回包含此错误的JAXBException: 我的问题是:这个错误意味着什么? 有什么解决方法吗? 备注: null 不同于类似的问题;我不认为这是一个元素名的大小写问题,因为元素名“head”根本没有出现在任何地方。我不完全理解为什么在错误消息中将uri标记为“”。 我尝试手动将@XMLRootElemen