Java 使用JAXB将xml与html实体解组

Java 使用JAXB将xml与html实体解组,java,xml,jaxb,Java,Xml,Jaxb,我需要将wikipedia的修订历史加载到POJO中,所以我使用JAXB来解组wikipeida数据转储(好的,它的各个页面)。问题是文本节点偶尔包含wikipedia xml转储中未定义的实体。例如:°(`°;'请记住,我不知道需要能够读取的完整实体集。我的输入文件是3tb,所以让我们假设html可以呈现的所有内容都在其中。) 如何配置JAXB来处理无效xml的实体 以下是JAXB遇到未定义实体时引发的SAX异常: Exception in thread "main" javax.xml

我需要将wikipedia的修订历史加载到POJO中,所以我使用JAXB来解组wikipeida数据转储(好的,它的各个页面)。问题是文本节点偶尔包含wikipedia xml转储中未定义的实体。例如:°(`°;'请记住,我不知道需要能够读取的完整实体集。我的输入文件是3tb,所以让我们假设html可以呈现的所有内容都在其中。)

如何配置JAXB来处理无效xml的实体

以下是JAXB遇到未定义实体时引发的SAX异常:

Exception in thread "main" javax.xml.bind.UnmarshalException

 - with linked exception:

[org.xml.sax.SAXParseException: The entity "deg" was referenced, but not declared.]

    at javax.xml.bind.helpers.AbstractUnmarshallerImpl.createUnmarshalException(AbstractUnmarshallerImpl.java:315)

    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.createUnmarshalException(UnmarshallerImpl.java:481)

    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:199)

    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:168)

    at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:137)

    at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:184)

    at com.stottlerhenke.tools.wikiparse.WikipediaIO.readPage(WikipediaIO.java:73)

    at com.stottlerhenke.tools.wikiparse.WikipediaIO.main(WikipediaIO.java:53)

Caused by: org.xml.sax.SAXParseException: The entity "deg" was referenced, but not declared.

    at org.apache.xerces.util.ErrorHandlerWrapper.createSAXParseException(Unknown Source)

    at org.apache.xerces.util.ErrorHandlerWrapper.fatalError(Unknown Source)

    at org.apache.xerces.impl.XMLErrorReporter.reportError(Unknown Source)

    at org.apache.xerces.impl.XMLErrorReporter.reportError(Unknown Source)

    at org.apache.xerces.impl.XMLScanner.reportFatalError(Unknown Source)

    at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanEntityReference(Unknown Source)

    at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl$FragmentContentDispatcher.dispatch(Unknown Source)

    at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)

    at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)

    at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)

    at org.apache.xerces.parsers.XMLParser.parse(Unknown Source)

    at org.apache.xerces.parsers.AbstractSAXParser.parse(Unknown Source)

    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:195)
编辑:触发该异常的输入是上维基百科文章的完整修订历史记录。用于生成JAXB类的XSD如下所示:


编辑:这个问题的根源是我的一个错误——我使用的初始提取器没有正确维护编码的实体。然而,我确实找到了解决这个问题的方法,如果有人遇到我认为我遇到的问题。请参见下文。

解析实体不是JAXB的工作。这是底层的工作 XML解析器

你能做的是:

  • 使用DOM自己读取数据
  • 用您希望的内容替换所有未解析的实体
  • 然后,让JAXB处理结果

这是一个黑客攻击,但它在紧要关头起作用

我从w3.org下载了html实体定义,并将输入xml文件的doctype设置为xhtml transitional,但将doctype url定向到本地dtd:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "xhtml1-transitional.dtd">

反过来,xhtml1-transitional.dtd需要:

  • xhtml-lat1.ent
  • xhtml-special.ent
  • xhtml-symbol.ent
我把它吸了下来,放在xhtml1-transitional.dtd的旁边

(所有文件可在以下位置获得:)


正如我所说,非常难看,但它似乎确实起到了作用。

由于Jaxb从XML解析器中抽象出来,我认为它应该提供一些方法来修复需要在解析器级别管理的事情(可能只是通过使用依赖项注入来提供不同的解析器)。然后,我又给了JAXB无效的输入——那么我期望得到什么呢?;)您是否有理由将dtd文档设置为本地文档?删除DTD文档时发生了什么?当JAXB试图直接检索DTD时,w3.org返回了一个错误代码——即使url在浏览器中工作。我推测w3.org正在基于用户代理阻止对dtd/etc的访问,以阻止人们从api访问他们的服务器。(w3.org在大约一年前呼吁人们停止编写这样做的应用程序:)我不知道“删除DTD文档时发生了什么事?”是什么意思。您可能希望使用XML目录指向本地副本,而不是更改DOCTYPE本身。有关详细信息,请参阅。