我有一个针对XML模式有效的XML文档。 XML模式具有组元素(xs:group)。这些组由其他定义的元素组成。如何编写一个XPath表达式,该表达式将为我提供指定组的所有成员?
有任何想法吗?
@Steve:
假设我的xml模式已定义了4个元素(elem1,elem2,elem3,elem4)。另外,将两个组定义如下:
group1: (elem1 | elem2 | elem3)
group2: (elem1 | elem4)
希望您知道一些正则表达式。如果否,则“ group2:(elem1 | elem4)”仅表示group2由elem1或elem4组成。
我的问题是,如果我有一个xml文档,例如:
<elem1/>
<elem2/>
<elem3/>
<elem4/>
<elem2/>
<elem1/>
<elem3/>
如何列出该文档中属于group1的元素
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<xs:element name="root">
<xs:complexType>
<xs:sequence>
<xs:element ref="elem0"/>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:group ref="A1"/>
<xs:group ref="A2"/>
</xs:choice>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="elem0" type="xs:string"/>
<xs:group name="A1">
<xs:choice>
<xs:element ref="elem10"/>
<xs:element ref="elem11"/>
</xs:choice>
</xs:group>
<xs:element name="elem10" type="xs:string"/>
<xs:element name="elem11" type="xs:string"/>
<xs:group name="A2">
<xs:choice>
<xs:element ref="elem20"/>
<xs:element ref="elem21"/>
<xs:element ref="elem22"/>
<xs:element ref="elem23"/>
</xs:choice>
</xs:group>
<xs:group name="CE">
<xs:choice>
<xs:element ref="elem30"/>
<xs:element ref="elem31"/>
<xs:element ref="elem32"/>
</xs:choice>
</xs:group>
<xs:group name="E">
<xs:choice>
<xs:element ref="elem30"/>
<xs:element ref="elem40"/>
</xs:choice>
</xs:group>
<xs:element name="elem20">
<xs:complexType>
<xs:sequence>
<xs:group minOccurs="2" maxOccurs="unbounded" ref="CE"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="elem21">
<xs:complexType>
<xs:sequence>
<xs:group minOccurs="2" maxOccurs="2" ref="CE"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="elem22">
<xs:complexType>
<xs:sequence>
<xs:element ref="elem40"/>
<xs:group ref="CE"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="elem23">
<xs:complexType>
<xs:sequence>
<xs:element ref="elem40"/>
<xs:element ref="elem40"/>
</xs:sequence>
<!-- <xs:attribute name="prop" use="required" type="xs:NMTOKEN"/> -->
</xs:complexType>
</xs:element>
<xs:element name="elem31">
<xs:complexType>
<xs:sequence>
<xs:group minOccurs="0" maxOccurs="unbounded" ref="CE"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="elem32">
<xs:complexType>
<xs:sequence>
<xs:group ref="CE"/>
</xs:sequence>
<!-- <xs:attribute name="prop" use="required"/> -->
</xs:complexType>
</xs:element>
<xs:element name="elem30">
<xs:complexType>
<xs:attribute name="name" use="required"/>
</xs:complexType>
</xs:element>
<xs:element name="elem40">
<xs:complexType>
<xs:attribute name="name" use="required"/>
</xs:complexType>
</xs:element>
</xs:schema>
最佳答案
好的...我认为我们需要在您的示例中澄清一些事情-因为尽管它们看起来像是小问题,但实际上并非如此-并且,如果您遵循规则,那应该是直截了当的-前进如何构造XPath表达式(我将展示有关如何构造基本XPath表达式的示例,其中将有效模式考虑到组的基础上,然后是您的示例所遇到的问题)。
让我们逐步进行。
序列组
首先,假设您有一个如下所示的架构:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<xs:element name="root">
<xs:complexType>
<xs:sequence>
<xs:group ref="group1"/>
<xs:group ref="group2"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:group name="group1">
<xs:sequence>
<xs:element name="elem1"/>
<xs:element name="elem2"/>
<xs:element name="elem3"/>
</xs:sequence>
</xs:group>
<xs:group name="group2">
<xs:sequence>
<xs:element name="elem1"/>
<xs:element name="elem2"/>
</xs:sequence>
</xs:group>
</xs:schema>
在这种情况下,需要注意的重要一点是我们有一个
group1
序列,后跟group2
都是元素序列。通过一个序列(并且
minoccurs='0'
元素上没有任何group
属性-仍然是无效的,正如我将在后面解释的那样),选择必需的元素很简单。要选择
group1
的所有元素,我们可以简单地使用以下XPath:/root/(elem1[1]|elem2[1]|elem3)
之所以可行,是因为我们知道生成的XML将始终是:
<root>
<elem1 />
<elem2 />
<elem3 />
<elem1 />
<elem2 />
</root>
所以,很好。我们可以始终选择第一个
elem1
,第一个elem2
和elem3
。有选择的团体
让我们假设它们包含选择,而不是包含序列的那些组。模式如下所示:
(这与您在示例中放入的模式类似,其中“ group2由elem1或elem4组成。”)
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<xs:element name="root">
<xs:complexType>
<xs:sequence>
<xs:group ref="group1"/>
<xs:group ref="group2"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:group name="group1">
<xs:choice>
<xs:element name="elem1"/>
<xs:element name="elem2"/>
<xs:element name="elem3"/>
</xs:choice>
</xs:group>
<xs:group name="group2">
<xs:choice>
<xs:element name="elem1"/>
<xs:element name="elem2"/>
</xs:choice>
</xs:group>
</xs:schema>
在这种情况下,XPath的构建仍然很简单,因为我们知道只有两个元素,第一个元素属于
group1
,第二个元素属于group2
,如下所示:<root>
<elem2 />
<elem1 />
</root>
因此,
group1
XPath更加简单:/root/*[1]
独特的粒子归因
这可能会使您感到困惑-而且,我相信,您可能会感到困惑。
在您的示例中,您基本上建议了以下架构:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<xs:element name="root">
<xs:complexType>
<xs:sequence>
<xs:group ref="group1" maxOccurs="unbounded"/>
<xs:group ref="group2" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:group name="group1">
<xs:choice>
<xs:element name="elem1"/>
<xs:element name="elem2"/>
<xs:element name="elem3"/>
</xs:choice>
</xs:group>
<xs:group name="group2">
<xs:choice>
<xs:element name="elem1"/>
<xs:element name="elem2"/>
</xs:choice>
</xs:group>
</xs:schema>
此架构无效。 (请注意,在组上添加了
maxOccurs="unbounded"
属性)。这类似于您的示例,其中显示了一组中出现的多个元素)。为什么?好吧,因为这会在生成的XML中造成潜在的歧义。
例如,我们应该如何解析以下XML实例:
<root>
<elem2 />
<elem1 />
<elem1 />
<elem2 />
</root>
就是它:
group1
,group1
,group1
,group1
或
group1
,group1
,group1
,group2
或
group1
,group1
,group2
,group1
或
group1
,group2
,group1
,group1
...
我们只是不知道。
但是XML Schema的设计者对此进行了思考,并为此制定了一条规则:
http://en.wikipedia.org/wiki/Unique_Particle_Attribution
并且您的假设方案违反了该规则。
现在,v1.1确实在这方面做了一些改进……但是,在某些情况下,您仍然可以轻松创建类似的歧义。
在您的示例中,如果xml中不存在元素3或4,则很难说出group1在哪里结束,group2在哪里开始。
现在,如果您要做的就是选择具有特定名称的元素,则可以轻松地做到这一点:
/root/(elementName1|elementName2|elementName3)
将选择
root
下名称为elementName1
或elementName2
或elementName3
的所有元素。因此,在您的示例中,类似:
(elem1|elem2|elem3)
就可以了。但是,那不是您要的。您要问的是关于按组选择的问题-您提供的示例使您无法为按组的问题提供真正的答案。
如果您有一个真实有效的架构,并且在构造XPath方面需要帮助,请粘贴该架构,我们将很乐意为您提供帮助。
关于xml - 如何在xpath中选择属于同一组的节点?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7814893/