从xsd中提取路径

时间:2013-03-05 18:26:58

标签: xml xsd schema

假设我有以下XML文档:

<foo>
  <bar/>
  <bang bash="hello">
    <foobar>123</foobar>
  </bang>
</foo>

我想提取本文档中各种叶子的所有路径列表,例如:

foo
foo.bar
foo.bang
foo.bang.@bash
foo.bang.foobar

这个过程有一个术语吗?

更进一步:假设我有一个真正极其复杂的XML模式的.xsd。有没有一种简单的方法从.xsd中提取所有这些路径?

(通过简单的方式,理想情况下,我的意思是某个库存在于某个地方吗?)

2 个答案:

答案 0 :(得分:2)

在SGML社区中,您要查找的值(当它们涉及元素时)被称为“完全限定的通用标识符”或FQGI;因为'。'是XML中的合法名称字符,在SGML参考具体语法中,FQGI通常用斜杠写入,您可以在其中写入点。 (我将在这里扩展术语FQGI并用它来表示你感兴趣的字符串,包括表示属性的字符串,而不是元素。)

我不知道找到所有FQGI集合的过程的任何既定术语,这些FQGI可能出现在针对特定模式有效的文档中。请记住,在许多XML词汇表中,这是一个无限集;如果你想要一个终止的过程,你需要确定所有可能的FQGI的有限子集。

但是你需要遵循的过程相对简单。一个简单的版本运行如下:

  1. 如果您感兴趣的架构是跨多个架构文档定义的,请将它们全部放在一个XML文档(一个包含多个xs:schema子项的包装器)或一个架构文档集合中。使用XSLT或XQuery处理。

  2. 标识您希望从中开始的元素声明和属性声明集。 (在您的情况下,此集合可能包含foo的顶级元素声明。)对于此集合中的每个项目,请记下其名称及其类型。调用这组字符串/类型对S.

  3. 将集合S复制到集合S'。

  4. 按以下方式创建一个集合S'':以S'开始为空,然后对于S'中的每个项目,让N为FQGI,T为项目中指定的类型,并且:

    (a)如果N表示属性,则不执行任何操作。

    (b)如果N表示一个元素,则标识可能出现在这样一个元素上的一组属性。对于每个此类属性,标识其类型T2,并通过连接N,斜杠,at符号和属性的扩展名称来创建字符串N2。将对(N2,T2)添加到S''。

    (c)如果N表示一个元素,则找到(i)出现在T的内容模型中的元素集合,(ii)匹配T的内容模型中的通配符,或者(iii)可替换为(i)或(ii)中指定的要素。对于每个这样的可能孩子,通过连接N,“/”和可能孩子的扩展名称来识别孩子的类型T3并创建字符串N3。将对(N3,T3)添加到S''。

  5. 如果S'为空,那么你就完成了,你的答案是在集合S和集合S'的并集中。否则,让(一个新的)S成为S和S'的并集,让(一个新的)S'等于S'',然后转到步骤4.

  6. 稍微反思会告诉您可以匹配通配符的名称集是无限的,因此步骤4(c)中的列表(ii)无法完整处理。您可以通过各种方式选择列表的有限子集;您选择的取决于您想要的FQGI列表。

    多一点反思会告诉你,如果词汇表中的任何元素都可以作为自己的后代出现(如HTML的div或li元素),那么概述的过程永远不会终止。同样,有多种方法可以修剪4(c)中生成的对,以保证终止。

    我不知道任何这样做的库,也许是因为有趣的XML词汇表很少有可能的FQGI集。使用XQuery引擎或XSLT样式表很容易。

答案 1 :(得分:1)

A similar question发布在此处。除了我在相关文章中描述的解决方案之外,我仍然不知道您的方案有任何开箱即用的解决方案(API或其他)。

我是第一个认识到我在SO上描述的the solution可能缺乏对某些XSD功能的报道,或者可能无法满足某人对如何生成某些XPath的具体期望。它可以支持更新的请求中的内容(包括其他“元数据”,例如XPath匹配的节点类型),因为可以使用自定义公式添加计算列以匹配您的模式。

虽然CM Sperberg-McQueen所描述的算法肯定会让你对它可能涉及的一些事情有所了解,但它也被一个关于简单思想方法的温和“免责声明”构成,这实际上意味着一些XSD规范涵盖的场景被排除在外。

除非您的XSD非常简单,否则请考虑一下预告片!一些“坏”的例子:通过复杂类型(不仅仅是元素引用)的递归XML结构(暗示)是棘手的,当XSD的设计中类型层次结构繁重且普遍时更是如此;使用抽象类型元素(想想实例XML中的xsi:type属性),使用块属性,表单属性,使用变色龙XSD(现在步骤1本身就很有趣,更不用说是否使用了不同的默认值对于模式级别的元素/属性表单。)

如果您发现某些额外的“详细信息”适用于您的XSD,那么我建议忘记XQuery或XSLT并使用专门的Schema Object Model API(Java上的XSOM,.NET也非常好用)一)遍历您的XSD - 在这里我只重复了@pgfearo所说的内容(据我所知,SAXON XSD支持仅在付费版本中提供;而Apache和JAXB RI免费为您提供XSOM)。那时你不需要担心很多事情,而且很可能你会在合理的时间内完成它。