Java 如何从XSD获取所有XPath?

Java 如何从XSD获取所有XPath?,java,xpath,xsd,Java,Xpath,Xsd,我有一个XSD,要求将XSD中存在的所有元素的xpath列出到UI中,以便用户可以使用它执行一些与DOM相关的操作 我可以通过编程从XSD中提取所有元素的XPath吗 Node n = doc.getFirstChild(); NodeList nl = n.getChildNodes(); 然后,您可以尝试遍历节点列表并获取每个节点的XPath String getXPath(Node node) { Node parent = node.getParent(); if (p

我有一个XSD,要求将XSD中存在的所有元素的xpath列出到UI中,以便用户可以使用它执行一些与DOM相关的操作

我可以通过编程从XSD中提取所有元素的XPath吗

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) + "/";
}

这是可以做到的,不过您需要知道所有允许的路径集都是无限的(例如,由于递归或通配符),因此您需要这个无限集的智能表示,或者如果您发现列表无法枚举,您的代码将需要放弃并返回类似“anything goes”的内容。支持模式的Saxon产品在对照模式检查路径表达式(如//para)时会执行类似的操作:如果它知道上下文项的类型,它可以确定//para是否能够选择任何内容,如果不能,它会给您一个警告

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

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

当然,当您知道元素名称与其允许的子元素之间的关系时,路径集就是这种关系的传递闭包。

我一直在研究一种方法,该方法用于1)提取xml文档本身(例如,模式定义文档)中存在的元素的所有XPath,或者2)列出在XSD描述的xml文档中可能找到的所有XPath

如果您只对1)问题和我的解决方案感兴趣,请访问

对于2),事情要复杂得多,尽管事实上我使用了1)作为起点,并且1)(
XpathXmlEnumerator
)和2)(
XpathXsdEnumerator
)共享一个公共接口(
XpathEnumerator
),不管值多少。虽然2)要长得多,但我估计在500 LOC左右,这仍然是一个相当精简的实现,考虑到所有因素(但可能需要更多的注释-请让我添加它们!)@michael kay在描述许多困难和概述可能的解决方案方面做得很好。也许不幸的是,我没有按照他的建议使用理解模式组件模型的软件,但我确实使用了
scala.xml
来尝试简化xml节点的工作。尽管如此,我相信我克服了所有已知的生成XPath的困难,因为XSD中有大量的信息/节点不需要为了在XSD描述的文档中生成XPath而理解,因此可以简单地忽略这些节点

过滤的思想对于避免计算随处可见且实际上并不关心的节点变得非常重要,并且还可能避免递归。但是,递归应该由2)中的实现自动检测,避免进一步遍历给定的xpath。对于筛选器,支持开始使用自定义
NodeFilters
类-有关用法示例,请参见
DdiCodebookSpec

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


虽然解决方案是Scala的,但我很乐意创建一个Java包装器(如果需要的话,它可以直接工作),如果有人真的需要,甚至可以将它发布到Maven。

模式语言很复杂,允许使用诸如
maxOccurs=“unbounded”之类的东西
或者对于递归,即实例文档可以包含的元素数量不受限制,您希望如何提取所有元素的XPath表达式?还有,元素的路径是什么,因为可以通过多种方式选择某个节点。我不完全清楚这个问题是问XSD xml文档本身中元素的xpath,还是问XSD描述的xml文档中可能存在的所有xpath的列表。在下面的回答中,我将尝试提供我为这两种情况所做的解决方案的参考。感谢您的回答-我在这篇文章的回答中描述了我的实现,我主要使用它作为基础,它只依赖于scala.xml(它曾经是标准库的一部分!)。仍然有一些粗糙的边缘,但随着使用和兴趣的增加,希望它能变得更加普遍有用。