想象一下,您有一個XML文檔,並想象您擁有DTD,但文檔本身並未實際指定DOCTYPE
......您如何插入DOCTYPE
聲明,最好通過在解析器上指定它(類似於您可以如何設置將被解析的文檔的架構),或通過XMLFilter
等插入必要的SAX事件?將文檔類型插入XML文檔(Java/SAX)
我發現許多人提到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 ...任何其他選項?
在你不想做一個改變你的文章的底部剛剛看到。對於那個很抱歉。 – 2010-04-17 06:53:20
沒問題...這不一定是_bad_解決方案,如果您嘗試流式傳輸XML文檔而不是將其緩存在內存中,則不太實用。 我想你可以使用Transform API,請參閱:javax.xml.transform.Transformer.setOutputProperty()和javax.xml.transform.OutputKeys.DOCTYPE_SYSTEM。實際上,現在我朝這個方向看起來更遠了一點,也許我需要一個javax.xml.transform.sax.SAXResult? – 2010-04-19 13:14:54