xml - 如何在xpath中选择属于同一组的节点?

标签 xml select xpath schema

我有一个针对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,第一个elem2elem3

有选择的团体

让我们假设它们包含选择,而不是包含序列的那些组。模式如下所示:

(这与您在示例中放入的模式类似,其中“ 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>


就是它:


group1group1group1group1
group1group1group1group2
group1group1group2group1
group1group2group1group1
...


我们只是不知道。

但是XML Schema的设计者对此进行了思考,并为此制定了一条规则:

http://en.wikipedia.org/wiki/Unique_Particle_Attribution

并且您的假设方案违反了该规则。

现在,v1.1确实在这方面做了一些改进……但是,在某些情况下,您仍然可以轻松创建类似的歧义。

在您的示例中,如果xml中不存在元素3或4,则很难说出group1在哪里结束,group2在哪里开始。

现在,如果您要做的就是选择具有特定名称的元素,则可以轻松地做到这一点:

/root/(elementName1|elementName2|elementName3)

将选择root下名称为elementName1elementName2elementName3的所有元素。

因此,在您的示例中,类似:(elem1|elem2|elem3)就可以了。

但是,那不是您要的。您要问的是关于按组选择的问题-您提供的示例使您无法为按组的问题提供真正的答案。

如果您有一个真实有效的架构,并且在构造XPath方面需要帮助,请粘贴该架构,我们将很乐意为您提供帮助。

关于xml - 如何在xpath中选择属于同一组的节点?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7814893/

相关文章:

mysql - 如何检查哪个 ID 具有另一个属性的所有不同值?

javascript - Javascript 是否具有给定文档的原始源代码的内部知识?

java - 如何在android中转换图像url字符串

xml - Jenkins:指标 'JUnit' 的结果文件无效。结果文件已被跳过

linux - socket编程中如何使用select和FD_SET?

MySQL:同一行中某些条件下的 SELECT 值和最小值

java - 获取给定 HTML 元素 id 的 HTML 属性列表

xml - 使用Pig在XPath中进行嵌套解析

android - 将 TextView 置于相对布局中

ruby - XPATH 选择具有属性和文本的节点