我有一个XML文档,它对XML模式有效。 XML模式具有组元素(xs:group)。这些组由其他定义的元素组成。如何编写一个XPath表达式,它将为我提供指定组的所有成员?
有什么想法吗?
@Steve:
假设我的xml架构定义了4个元素( elem1,elem2,elem3,elem4 )。另外,2组定义如下:
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>
答案 0 :(得分:2)
好的......我认为我们需要在你的例子中澄清一些事情 - 因为,虽然它们看起来像小点,但实际上它们不是 - 而且,如果你遵守规则,它应该是直截了当的如何构造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 Schemas的设计者对此进行了思考并为此制定了规则:
http://en.wikipedia.org/wiki/Unique_Particle_Attribution
您的假设架构违反了该规则。
现在,v1.1确实在这方面做了一些改进......但是,仍然存在可以轻松创建类似歧义的情况。
在您的示例中,如果xml中不存在元素3或4,则无法确定group1的结束位置和group2的开始位置。
现在,如果您只想选择具有特定名称的元素,则可以轻松完成:
/root/(elementName1|elementName2|elementName3)
将选择名称为root
或elementName1
或elementName2
的{{1}}下的所有元素。
所以,在你的例子中,像elementName3
这样的东西就可以了。
但是,那不是你问的。你问的是关于按群组选择 - 而你提供的例子使你无法给出小组的真实答案。
如果你有真正的,有效的架构,并且需要帮助构建XPath,请粘贴那个架构,我会很乐意提供帮助。