X-Path 2.0 в XSD (assert): "count(//elem/text() = 'test') > 0" всегда true, даже если строка не совпадает
Я хочу использовать функцию подтверждения XSD1.1 для проверки элементов на уровне содержимого. (Если быть более точным, я хочу проверить наличие комбинаций содержимого в EDIFACT, представленных в XML, но это не главное...)
Чтобы проверить мои XPath, я создал следующий мини-тестовый сценарий:
XML
<root>
<group>
<elem1>test1</elem1>
<elem2>test2</elem2>
</group>
<group>
<elem1>something1</elem1>
<elem2>something2</elem2>
</group>
<group>
<elem1>other1</elem1>
<elem2>other2</elem2>
</group>
</root>
Требование: я хочу проверить, что у меня есть комбинация строки test1 + test2 и комбинации строки что-то1 и чего-то2. Могут быть группы, подобные группе other1 + other2, которая может быть там, но мне все равно. Порядок трех групп здесь также не должен иметь никакого влияния.
Я должен проверить XSD:
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="root">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="group" minOccurs="1" maxOccurs="unbounded">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="elem1" minOccurs="1">
</xsd:element>
<xsd:element name="elem2" minOccurs="1">
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
<xsd:assert test="(count(./group/elem1/text() = 'test1') > 0
and count(./group/elem2/text() = 'test2') > 0)
and (count(./group/elem1/text() = 'something1') > 0
and count(./group/elem2/text() = 'something2') > 0)"/>
</xsd:complexType>
</xsd:element>
</xsd:schema>
Интересный момент:
(count(./group/elem1/text() = 'test1') > 0
and count(./group/elem2/text() = 'test2') > 0)
and (count(./group/elem1/text() = 'something1') > 0
and count(./group/elem2/text() = 'something2') > 0)
или сломать это:
count(./group/elem1/text() = 'test1') > 0
Моя проблема заключается в следующем: выражение (если быть более точным) возвращает true, даже если строки не совпадают. Допустим, я проверяю на "test1", но моя строка "test":
./group/elem1/text() = 'test1'
в этом само работает. Он возвращает истину или ложь правильно. Но использование рассчитывать на это не работает. (Кажется, всегда возвращать истину)
Я предполагаю, что подсчет не является правильным решением здесь, дело в том, что я не хочу проверять каждую группу на "это точно", но после того, как все группы "делают это, и эта конкретная комбинация встречается хотя бы один раз" во всех повторениях из групп.
Я тестирую это на Saxon 9 EE, но XPath имеет такое же поведение и в других реализациях XPath.
Любая помощь будет принята с благодарностью.
Спасибо, э
редактировать:
После того, как это сработало с помощью Мадс Хансен и Майкла Кея (спасибо!), У меня было последнее препятствие для прыжка:
Рассмотрим этот случай:
<root>
<group>
<elem1>test1</elem1>
<elem2>WRONG</elem2>
</group>
<group>
<elem1>WRONG</elem1>
<elem2>test2</elem2>
</group>
</root>
с этим XPath
count (group [elem1 / text () = 'test1' и elem2/text() = 'test2']) > 0)
Теперь это приводит к тому, что приведенный выше пример НЕ действителен (как я хотел бы), в то время как исходный XPath я проверял выше, так как он не проверял внутри.
2 ответа
Вам нужно настроить XPath, чтобы отфильтровать искомые элементы, а затем посчитать, что осталось. Ваше текущее выражение оценивает, является ли какой-либо из group/elem1/text()
узлы равны test1
, который будет либо true()
или же false()
, а затем вы рассчитываете логическое значение.
Используйте предикат для проверки text()
значения и подсчитать, сколько удовлетворяют условию:
count(./group/elem1/text()[.='test1'])
Ответ:
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="root">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="group" minOccurs="1" maxOccurs="unbounded">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="elem1" minOccurs="1">
</xsd:element>
<xsd:element name="elem2" minOccurs="1">
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
<xsd:assert test="(count(group[elem1/text() = 'test1'
and elem2/text() = 'test2']) > 0)
and (count(group[elem1/text() = 'something1'
and elem2/text() = 'something2']) > 0 )"/>
</xsd:complexType>
</xsd:element>
</xsd:schema>
Подтвердит:
<root>
<group>
<elem1>test1</elem1>
<elem2>test2</elem2>
</group>
<group>
<elem1>test1</elem1>
<elem2>test4</elem2>
</group>
<group>
<elem1>something1</elem1>
<elem2>something2</elem2>
</group>
<group>
<elem1>other1</elem1>
<elem2>other2</elem2>
</group>
</root>