Представьте, что у вас есть документ XML, и представьте, что у вас есть DTD, но сам документ фактически не указывает DOCTYPE
... Как бы вы вставили объявление DOCTYPE
, предпочтительно указав его в анализаторе (аналогично как вы можете установить схему для документа, который будет анализироваться) или путем вставки необходимых событий SAX через XMLFilter
или тому подобное?
Я нашел много ссылок на EntityResolver
, но это то, что вызывается, когда DOCTYPE
найден найден во время синтаксического анализа и используется для указания на локальный файл DTD. EntityResolver2
, кажется, имеет то, что я ищу, но я не нашел никаких примеров использования.
Это самый близкий к этому моменту: (код Groovy, но достаточно близок, чтобы вы могли его понять ...)
import org.xml.sax.*
import org.xml.sax.ext.*
import org.xml.sax.helpers.*
class XmlFilter extends XMLFilterImpl {
public XmlFilter( XMLReader reader ) { super(reader) }
@Override public void startDocument() {
super.startDocument()
super.resolveEntity( null,
'file:///./entity.dtd')
println "filter startDocument"
}
}
class MyHandler extends DefaultHandler2 {
public InputSource resolveEntity(String name, String publicId, String baseURI, String systemId) {
println "entity: $name, $publicId, $baseURI, $systemId"
return new InputSource(new StringReader('<!ENTITY asdf "¡">'))
}
}
def handler = new MyHandler()
def parser = XMLReaderFactory.createXMLReader()
parser.setFeature 'http://xml.org/sax/features/use-entity-resolver2', true
def filter = new XmlFilter( parser )
filter.setContentHandler( handler )
filter.setEntityResolver( handler )
filter.parse( new InputSource(new StringReader('''<?xml version="1.0" ?>
<test>one &asdf; two! ¡£¢</test>''')) );
Я вижу, resolveEntity
позвонил, но все еще ударил
org.xml.sax.SAXParseException: На сущность "asdf" ссылались, но не объявляли.
на com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse (AbstractSAXParser.java:1231)
в org.xml.sax.helpers.XMLFilterImpl.parse (XMLFilterImpl.java:333)
Полагаю, это потому, что нет способа добавить события SAX, о которых знает парсер , я могу добавлять события только через фильтр, который находится выше по потоку от парсера и передается в ContentHandler. Таким образом, документ должен быть действительным при входе в XMLReader. Есть ли способ обойти это? Я знаю, что могу изменить необработанный поток, чтобы добавить тип документа или, возможно, выполнить преобразование, чтобы установить DTD ... Какие-либо другие параметры?