2015-06-30 66 views
1

我有一个XSD,并且需要将XSD中存在的所有元素的xpath列出到UI中,以便用户可以使用它来执行一些与DOM相关的操作。如何从XSD获取所有xpath?

我可以编程方式从XSD中提取所有元素的xpath?

+0

模式语言很复杂,并且允许像maxOccurs =“unbounded”这样的东西,或者用于递归意味着实例文档可以包含的元素数量不受限制,您如何期望能够提取XPath表达式所有元素?元素的路径又是什么,因为可以有几种方法来选择某个节点。 –

+0

对于我来说,如果这个问题询问XSD xml文档本身中存在的元素的xpath,或者更确切地说,是由XSD描述的xml文档中可能找到的所有可能的xpath的列表,我不完全清楚。我将尝试在下面的答案中提供我一直在为这两种情况开展工作的解决方案的参考。 – bbarker

回答

0
Node n = doc.getFirstChild(); 
NodeList nl = n.getChildNodes(); 

那么你可以尝试去通过节点列表,并获得每个节点的XPath

String getXPath(Node node) 
{ 
    Node parent = node.getParent(); 
    if (parent == null) { 
     return "/" + node.getTagName(); 
    } 
    return getXPath(parent) + "/"; 
} 
1

这是可以做到,但你需要知道的是,集所有允许的路径是无限的(例如因为递归或通配符),所以你将需要这个无限集合的智能表示,否则你的代码将需要放弃并返回类似“任何事情”的东西,如果你发现列表不能被枚举。架构感知的Saxon产品在检查路径表达式(例如.//para)与模式时检查某些内容:如果它知道上下文项的类型,则可以确定.//para是否能够选择任何内容,如果不是,给你一个警告。

作为第一步,你需要建立(相关部分)从源模式文件的架构组件模型。不要试图自己做这件事,这是太多的工作。许多产品都有一个API,允许您访问模式组件模型。 Saxon允许您使用Validate命令行上的-scmout标志,以XML表示形式从源模式文档生成模式组件模型。

一旦你有了模式组件模型,你可以通过转到它的复杂类型(如果它是一个简单的类型,那么答案是微不足道的)并且遍历粒子树,只查找元素粒子和通配符粒子(你可能会认为如果有通配符粒子,最好放弃)。您可能不仅要考虑元素的声明类型,还要考虑通过扩展从其中派生的其他类型。您需要知道允许的子元素的元素声明,而不仅仅是允许的子元素名称,因为当然,在查找允许的孙子时,您需要从元素声明开始,因为可能会有元素的本地声明同名。

当你知道元素的名称和他们的孩子允许元素之间的关系,当然还有,设定的路径是这种关系的传递闭包。

+0

感谢您的回答 - 我已经在很大程度上将它用作我在本文回复中描述的实现中的基础,该回复仅依赖于scala.xml(并且曾经是标准库的一部分!)。仍然有一些粗糙的边缘,但有用和兴趣,希望它可以做得更普遍有用。 – bbarker

0

我一直在研究project,它具有以下方法:1)提取xml文档中存在的所有xpath文档(例如,模式定义文档); 2)列出所有可能的xpath由XSD描述的xml文档。

如果你只在1兴趣)的问题,我的解决方案已经在Scala: What is the easiest way to get all leaf nodes and their paths in an XML?

对于图2中的Scala)描述,并回答了(虽然),事情要复杂得多,但其实我用1)作为出发点,1)(XpathXmlEnumerator)和2)(XpathXsdEnumerator)共享一个通用接口(XpathEnumerator),无论值多少。虽然2)更长,但我在〜500 LOC的时候它仍然是一个相当精益的实现,所有的事情都考虑过了(但是可能会使用更多的评论 - 请注意我添加它们!)。 @迈克尔凯在描述许多困难和概述可能的解决方案方面做了很多工作。也许不幸的是,我没有按照他的建议来使用理解模式组件模型的软件,但我确实使用scala.xml来尝试简化与xml节点的工作。尽管如此,我相信我克服了生成xpath的所有已知困难,因为XSD中的信息/节点的比例很高,为了在由XSD描述的文档中生成XPath,不需要理解,所以一个可以简单地忽略这些节点。

过滤的想法变得非常重要,以避免出现无处不在的计数节点,并且您在实践中并不关心,也可能避免递归。然而,递归应该被2)中的实现自动检测到,避免了进一步遍历给定的xpath。对于过滤器,支持使用自定义NodeFilters类的开始 - 有关示例用法,请参阅DdiCodebookSpec

您可以在与ShipOrderXsdSpec相同的目录中看到项目中运行的一些测试,其中包含一些快速运行的示例,如果您想尝试一下。其他一些测试不能很快运行,有些测试存在问题 - 这是“pre-alpha”软件!

尽管解决方案在Scala中,但我很乐意创建一个Java包装器(如果需要的话 - 它可能会直接工作),甚至可以将它发布到Maven,如果任何人想要的话。