从Xerces的DOM中获取XML实体替换文本

| doc0ѭ的Javadoc指出:   XML并不要求非验证XML处理器读取和处理在外部子集中或在参数实体中声明的实体声明。这意味着某些子类的应用程序无需扩展在外部子集中声明的已解析实体,并且该实体的替换文本可能不可用。当替换文本可用时,相应的“实体”节点的子级列表表示该替换值的结构。否则,子列表为空。 虽然它不引用内部子集中的实体声明,但肯定要有一些解析器配置,可以读取和处理任一子集中的实体声明?实际上,我对文档的阅读表明这是默认设置。 无论如何,我已经针对内部子集(如图所示)和外部子集中声明的实体测试了以下方法(使用Xerces),但是在每种情况下
foo.hasChildNodes()
返回false(and2ѭ返回ѭ3!!):
// some trivial example XML
String xml = \"<!DOCTYPE example [ <!ENTITY foo \'bar\'> ]>\\n<example/>\";
InputStream is = new ByteArrayInputStream(xml.getBytes());

// parse
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
DocumentType docType = builder.parse(is).getDoctype();

// retrieve the entity - works fine
Entity foo = (Entity) docType.getEntities().getNamedItem(\"foo\");

// now how to get the entity\'s replacement text?
毫无疑问,我缺少了一些显而易见的东西。感谢您的想法。 编辑 到目前为止的答案似乎表明我的Xerces实现行为异常。我将尝试将所有Xerces库更新为最新版本,如果能够解决我的问题,我将结束该问题。非常感谢。 更新 只要从文档中引用实体,更新Xerces确实可以解决问题。如果不是,则该节点仍然没有子节点。我尚不完全清楚为什么会这样。如果有人可以解释正在发生的事情和/或向我指出如何在不显式引用文档中每个实体的情况下强制创建子节点,将不胜感激。     
已邀请:
我认为您可能会误认为替换文字的工作方式。根据一些阅读(http://www.javacommerce.com/displaypage.jsp?name=entities.sql&id=18238),在我看来替换文本就像一个变量一样工作。因此,在上面的示例中,您从未引用过“ 5”实体。如果运行下面的代码示例,您将看到发生的情况是将
&foo;
替换为字符串
bar
// some trivial example XML
String xml = \"<!DOCTYPE example [ <!ENTITY foo \'bar\'> ]><example><foo>&foo;</foo></example>\";
InputStream is = new ByteArrayInputStream(xml.getBytes());

// parse
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(is);
DocumentType docType = doc.getDoctype();

// retrieve the entity - works fine
Entity foo = (Entity) docType.getEntities().getNamedItem(\"foo\");
for(int i = 0; i < foo.getChildNodes().getLength(); i++) {
  System.out.println(foo.getChildNodes().item(i));
}
您看到的是“ 9”,它是XML中的文本替换。     
我可能是错的,但是我认为实体节点将替换文本存储为文本值,而不是节点集。这是因为在解析实体定义时实际上并未完全解析实体:这主要是因为DTD处理程序是一种在实际解析过程之前发生的预处理程序。 因此,请检查实体节点而不是子节点列表的文本值。     
我不知道为什么
foo.getChildNodes()
不起作用,但是我发现了以下内容。如果在文档中使用(引用)了该实体,
<!DOCTYPE example [<!ENTITY foo \'bar\'>]>\\n<example>&foo;</example>
, 那么替换文本可以通过
foo.getTextContent()
    
我在Xerces-J用户邮件列表中询问了文档中未引用实体的子节点不存在的情况。迈克尔·格拉瓦瑟维奇(Michael Glavassevich)帮我指出了安迪·克拉克(Andy Clark)的一则旧帖子,内容如下:   不幸的是(对您来说)这是一个功能。并实现了   这种方式主要是出于性能原因。如果一个实体永远不会   在文档中引用,那么我们就不必浪费时间   阅读它。如果外部实体很大但从未引用,   我们不会浪费时间或记忆。      此外,与名称空间有关的问题更深。 DOM   甚至都帮不上忙我会解释...      获取以下文档和外部实体:
  <!-- entity.ent -->
  <hello/>

  <!-- document.xml -->
  <!DOCTYPE root [
  <!ENTITY entity SYSTEM \'entity.ent\'>
  ]>
  <root>
    <sub xmlns=\'foo\'> &entity; </sub>
    <sub xmlns=\'bar\'> &entity; </sub>
  </root>
     请注意,默认名称空间在每一点上都是不同的   引用实体的位置。这意味着   元素将绑定到不同的名称空间。所以两者   同一实体的实例实际上是不同的元素!      在这种情况下,DOM文档类型中的Entity节点应该是什么?   返回:\“ foo \”名称空间中的子级或\“ bar \”中的子级   命名空间?      简而言之,这是一个复杂的问题。      您可能最好尝试阅读文档片段   自己,当您寻找实体节点时,它没有   孩子们。 Xerces在impl中有一个文档碎片扫描器   软件包将对此有用。你必须   编写为DOM文档片段构建子代的代码   但是,它来自XNI方法。但这并不难。我可以   如果需要,请为您提供示例。     

要回复问题请先登录注册