将多个DTD合并为一个或重用公共部分

时间:2016-02-16 11:11:11

标签: xml libxml2 xml-dtd

我有许多用于不同XML文档类型的外部DTD。所有DTD都非常相似:包括常见的DTD定义,然后是5-10行文档类型特定定义,这些定义依赖于通用定义。虽然具体定义很短,但常见的定义很大。

是否有可能以某种方式将所有这些小型外部DTD组合成一个大的DTD?

我遇到的具体问题是DTD解析的开销。第一个想法是缓存解析的DTD。然而这个想法失败了,因为正如我所发现的,每一个DTD(使用libxml2 v2.9.2)都需要大约1.1MB的RAM:乘以~25,即DTD的数量,远远高于我们的内存限制。由于99%的DTD实际上是相同的通用定义,我正在寻找以某种方式重用公共部分的方法。

1 个答案:

答案 0 :(得分:0)

(回复自己。)

  

是否有可能以某种方式将所有这些小型外部DTD组合成一个大的DTD?

这似乎是不可能的。我还没有找到任何官方方法来实现这一目标。

libxml2似乎也没有提供任何非标准设施来实现这一目标。

  

我正在寻找以某种方式重用公共部分的方法。

在libxml2的帮助下深入分析问题,我找到了两种可能性。

  1. 优化DTD。在加载DTD之后,扩展包含/实体,并且DTD成为锚定在DTD节点处的子节点(元素,实体,属性等)的平面列表。从顶级节点(对应于DOCTYPE)开始,可以导出实际使用的(+)DTD子节点的列表,并删除未使用的所有内容。然后,使用转储功能,一次可以将剩余的条目写入新的DTD文件,该文件现在应该比原始文件小得多。 ((+)虽然似乎不支持DTD子节点的深度内省,但仍然可以从节点的字符串表示中提取信息。)

  2. 从公共和特定于文档类型的定义中动态组合内存中的DTD。通过libxml2 API,我找到了一个允许在内存中扩展解析后的DTD的函数:xmlAddElementDecl()xmlAddAttributeDecl()。 API似乎很简陋。但至少,似乎有可能:加载公共部分;加载文档类型特定部分;暂时,在功能的帮助下,将子节点从后面移动(或复制)到前者。移动后,内存中的DTD结构应与原始DTD的DTD结构几乎相同。之后,在执行验证后,可以移回(或释放子节点的副本),以使(大)公共部分可以再次重复使用。

  3. 不幸的是,目前我没有时间在实践中测试这两种方法。