Я хочу использовать функцию утверждения 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 и комбинация строк something1 и something2. Могут быть группы, подобные группе 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

Моя проблема: выражение (если быть более точным, считать) возвращает истину, даже если строки не совпадают. Скажем, я тестирую "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 (группа [elem1 / text () = 'test1' и elem2 / text () = 'test2'])> 0)

Теперь это приводит к тому, что приведенный выше пример НЕ является действительным (как я хотел бы), в то время как исходный XPath я проверил выше, поскольку он не проверял внутри.

3
eee 10 Май 2016 в 17:41

2 ответа

Лучший ответ

Вам нужно настроить XPath, чтобы отфильтровать элементы, которые вы ищете, а затем подсчитать, что осталось. Ваше текущее выражение оценивает, равен ли какой-либо из узлов group/elem1/text() test1, который будет либо true(), либо false(), а затем вы подсчитываете логическое значение.

Используйте предикат, чтобы проверить значения text() и подсчитать, сколько из них удовлетворяет условию:

count(./group/elem1/text()[.='test1'])
3
Mads Hansen 10 Май 2016 в 15:08

Ответ:

<?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>
0
eee 19 Май 2016 в 13:04