I have an XSD and the requirement is to list the xpath of all the elements present in XSD into UI, so users can use it to perform some DOM related operations.
Can I programatically extract xpaths of all the elements from XSD?
答案 0 :(得分:1)
可以这样做,虽然你需要知道所有允许路径的集合是无限的(例如因为递归或因为通配符)所以你需要这个无限集的智能表示,或者你的代码将如果你发现列表无法枚举,就需要放弃并返回类似“任何事情”的内容。当检查路径表达式(例如.//para对模式)时,模式感知的Saxon产品做了类似的事情:如果它知道上下文项的类型,它可以确定.//para是否能够选择任何东西,如果没有,就给你一个警告。
作为第一步,您需要从源架构文档构建架构组件模型的(相关部分)。不要试图自己这样做,这是太多的工作。许多产品都有一个API,允许您访问架构组件模型。 Saxon允许您使用Validate命令行上的-scmout标志,从源模式文档生成模式组件模型作为XML表示。
一旦你有了模式组件模型,你可以通过转到它的复杂类型(如果它是一个简单的类型然后答案是微不足道的)来找到一个元素的允许子元素,并递归地遍历粒子树,只查找元素粒子和通配符粒子(你可能会认为如果有通配符粒子,最好放弃)。您可能不仅要考虑元素的声明类型,还要考虑通过扩展从该元素派生的其他类型。您需要知道允许的子元素的元素声明,而不仅仅是允许的子元素名称,因为当然在查找允许的孙子元素时,您需要从元素声明开始,因为可能存在元素的局部声明同名。
当然,当你知道元素名称和它们允许的子元素之间的关系时,路径集就是这种关系的传递闭包。
答案 1 :(得分:0)
Node n = doc.getFirstChild();
NodeList nl = n.getChildNodes();
Then you can try to go through the list of nodes and get each node XPath
String getXPath(Node node)
{
Node parent = node.getParent();
if (parent == null) {
return "/" + node.getTagName();
}
return getXPath(parent) + "/";
}
答案 2 :(得分: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?
中进行了描述和解答(尽管在Scala中)对于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,如果有人真的想要它。