XML desarrumante com entidades HTML usando JAXB
Pergunta
Eu preciso carregar histórias de revisão da Wikipedia em Pojos, por isso estou usando o JAXB para soltar o dump de dados do Wikipeida (bem, páginas individuais). O problema é que os nós de texto ocasionalmente contêm entidades que não são definidas no dump da Wikipedia XML. Por exemplo: ° (`° 'bem, lembre -se de que não conheço o conjunto completo de entidades que preciso para poder ler. Meu arquivo de entrada é 3TB, então vamos apenas assumir que tudo o que o HTML pode renderizar está lá.) .
Como posso configurar o JAXB para lidar com entidades que não são XML válidas?
Aqui está a exceção sax que Jaxb joga quando encontra uma entidade indefinida:
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)
Editar: A entrada que desencadeou essa exceção é o histórico completo de revisão do artigo da Wikipedia no circulo Ártico. O XSD usado para gerar as classes JAXB está aqui: http://www.mediawiki.org/xml/export-0.3.xsd
Editar: A fonte desse problema foi um erro da minha parte - eu estava usando um extrator inicial que não mantinha entidades codificadas corretamente. No entanto, encontrei uma maneira de contornar isso, caso alguém tivesse o problema que eu pensamento Eu tive. Veja abaixo.
Solução 2
Este é um hack, mas funciona em uma pitada.
Baixei as definições de entidade HTML do W3.org e defino o doctype do arquivo XML de entrada para XHTML transitório, mas direcionei o URL do Doctype para um DTD local:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "xhtml1-transitional.dtd">
xhtml1-transitional.dtd, por sua vez, requer:
- xhtml-lat1.ent
- xhtml-special.ent
- xhtml-symbol.ent
que eu chupei e coloquei o lado xhtml1-transitional.dtd
(Todos os arquivos estão disponíveis em: http://www.w3.org/tr/xhtml1/dtd/ )
Como eu disse, feio como o inferno, mas fez parecem fazer o trabalho.
Outras dicas
Resolver entidades não é o trabalho da Jaxb. É o trabalho do analisador XML subjacente.
O que você poderia fazer é:
- Leia os dados usando o DOM
- substitua todas as entidades não resolvidas por algo que você deseja
- Então, deixe o JAXB lidar com o resultado