我正在解析(很多)包含实体引用的XML文件,我事先并不知道(不能改变这个事实).
例如:
xml = "<tag>I'm content with &funny; &entity; &references;.</tag>"
Run Code Online (Sandbox Code Playgroud)
当我尝试使用以下代码解析它:
final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
final DocumentBuilder db = dbf.newDocumentBuilder();
final InputSource is = new InputSource(new StringReader(xml));
final Document d = db.parse(is);
Run Code Online (Sandbox Code Playgroud)
我得到以下异常:
org.xml.sax.SAXParseException: The entity "funny" was referenced, but not declared.
Run Code Online (Sandbox Code Playgroud)
但是,我想要实现的是,解析器用空字符串''替换未声明的每个实体(解析器未知).或者甚至更好,有没有办法将地图传递给解析器,如:
Map<String,String> entityMapping = ...
entityMapping.put("funny","very");
entityMapping.put("entity","important");
entityMapping.put("references","stuff");
Run Code Online (Sandbox Code Playgroud)
这样我就可以做到以下几点:
final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
final DocumentBuilder db = dbf.newDocumentBuilder();
final InputSource is = new InputSource(new StringReader(xml));
db.setEntityResolver(entityMapping);
final Document d = db.parse(is);
Run Code Online (Sandbox Code Playgroud)
如果我使用这个示例代码从文档中获取文本,我应该收到:
I'm content with very important stuff.
Run Code Online (Sandbox Code Playgroud)
有什么建议?当然,我已经很乐意用空字符串替换未知实体.
谢谢,
StAX API 对此提供支持。看一下XMLInputFactory,它有一个运行时属性,该属性指示内部实体是展开还是保留在原处。如果设置为false,则 StAX 事件流将包含 的实例EntityReference来表示未展开的实体。
如果您仍然想要 DOM 作为最终结果,您可以将其链接在一起,如下所示:
XMLInputFactory inputFactory = XMLInputFactory.newInstance();
inputFactory.setProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, false);
Transformer transformer = TransformerFactory.newInstance().newTransformer();
String xml = "my xml";
StringReader xmlReader = new StringReader(xml);
XMLEventReader eventReader = inputFactory.createXMLEventReader(xmlReader);
StAXSource source = new StAXSource(eventReader);
DOMResult result = new DOMResult();
transformer.transform(source, result);
Node document = result.getNode();
Run Code Online (Sandbox Code Playgroud)
在这种情况下,生成的 DOM 将包含org.w3c.dom.EntityReference与文本节点混合的节点。然后您可以根据需要处理这些内容。