ОК ... есть несколько вещей, которые, я думаю, нам нужно прояснить в вашем примере - потому что, хотя они могут показаться незначительными, на самом деле это не так - и, если вы следуете правилам, это Должно быть понятно, как создать выражение 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
обе из которых последовательности элементов.
С sequence , (и без атрибута minoccurs='0'
на любом из элементов group
- что в любом случае будет недопустимым, как я объясню позже), выбор необходимых элементов тривиален.
Чтобы выбрать все элементы group1
, мы могли бы просто использовать следующий XPath:
/root/(elem1[1]|elem2[1]|elem3)
Это работает, потому что мы знаем, что полученный XML будет всегда быть:
<root>
<elem1 />
<elem2 />
<elem3 />
<elem1 />
<elem2 />
</root>
Итак, все в порядке. Мы всегда можем выбрать первые elem1
, первые elem2
и elem3
.
Группы с выбором
Предположим, что вместо групп, содержащих последовательности, вместо них содержалось вариантов . Схема выглядит следующим образом:
(Это больше похоже на схему, которую вы положили в своем примере, где «группа2 состоит из ЛИБО элемент1 ИЛИ элемент4».)
<?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-схем подумали об этом и разработали правило для этого:
http://en.wikipedia.org/wiki/Unique_Particle_Attribution
И ваша гипотетическая схема нарушает это правило.
Теперь в версии 1.1 внесены некоторые улучшения в этой области ... однако, все еще существуют ситуации, в которых вы можете легко создать подобные неоднозначности.
В вашем примере, если в xml нет элементов 3 или 4, на самом деле совершенно невозможно определить, где заканчивается group1 и group2.
Теперь, если все, что вам нужно, это выбрать элементы с определенным именем, вы можете сделать это легко:
/root/(elementName1|elementName2|elementName3)
выберет все элементы в root
с именами elementName1
или elementName2
или elementName3
.
Итак, в вашем примере что-то вроде: (elem1|elem2|elem3)
было бы просто отлично.
Но это не то, что вы спросили. То, что вы спросили, было о выборе по группе - и приведенный вами пример лишил возможности дать вам реальный ответ для по группе .
Если у вас есть реальная , действительная схема и вам нужна помощь в создании XPath, вставьте эту схему, и я буду рад Помогите.