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>
Другие вопросы по тегам