2016-05-10 3 views
3

Я хочу использовать функцию утверждения XSD1.1 для проверки элементов на уровне контента. (Чтобы быть более точным, я хочу проверить наличие комбинаций контента в EDIFACT, представленных в XML, но это не главное ...)X-Path 2.0 в XSD (assert): "count (// elem/text() = 'test')> 0" всегда true, даже если строка не соответствует

Чтобы проверить мои XPaths, я построил следующий мини-тест- сценарий:

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 

Моя проблема заключается в следующем: выражение (счетчик будет более конкретным) возвращает true, даже если строки не совпадают. Скажем, я тестирую тест «test1», но моя строка является «тестом»:

./group/elem1/text() = 'test1' 

0 0 0 0 0 0 Он корректно возвращает true или false. Но использование счета на нем не работает. (Кажется, всегда возвращает true)

Я предполагаю, что подсчет не является правильным решением здесь, дело в том, что я не хочу тестировать каждую группу на «это точно», но после всех групп «делает это и это конкретная комбинация происходит по крайней мере один раз «во всех повторениях групп.

Я тестирую это на Saxon 9 EE, но XPath имеет такое же поведение и в других реализациях XPath.

Любая помощь была бы принята с благодарностью.

Спасибо, е


редактировать:

После того, как эту работу с помощью Мадс Хансен и Майкл Кей (! Спасибо) У меня был один последний барьер прыгать:

Рассмотрим этот случай:

<root> 
    <group> 
     <elem1>test1</elem1> 
     <elem2>WRONG</elem2> 
    </group> 
    <group> 
     <elem1>WRONG</elem1> 
     <elem2>test2</elem2> 
    </group> 
</root> 

с этим XPath

Количество (группа [elem1/текст() = 'test1' и elem2/текст() = 'test2'])> 0)

Это приводит теперь к приведенный выше пример является не действует (как я бы например,), в то время как оригинальный XPath I подтвердил это выше, поскольку он не проверял внутри.

ответ

3

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

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

count(./group/elem1/text()[.='test1']) 
+1

Есть ли разница с 'count (./ group/elem1 [text() = 'test1'])'? – splash58

+0

Нет, либо будет работать, либо получить тот же результат. –

+4

Обратите внимание: вы можете упростить 'test = 'count (./ x/y [text() =' TTT '])> 0" 'to' test = "x/y =' TTT '" '. –

0

Ответ:

<?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> 
Смежные вопросы