2015-02-26 5 views
2

Я пытаюсь найти лучший способ проверки нижеприведенного XML-документа. Я рассмотрел три способа сделать это до сих пор:XML Validation - If Then

DTD - не похоже, что есть достаточно вариантов, чтобы это произошло.

XSD - почти работает, но я не могу найти способ сделать что-то вроде If Then

XSL - О той же проблемой, что я могу сделать, если, но я не могу понять способ заставить его работать против этого документа.

Идея такова: Корневой элемент <Answers>. Под 1 или более <Answer>. Они имеют атрибут идентификатора, обозначающий номер вопроса (обрабатываемый в другом месте, а не важный), который соответствует. Каждый вопрос может иметь 0 или больше ответов, которые в настоящее время написаны сейчас, как <A1>, <A2> ... Каждый ответ имеет 1 или более элементов, которые входят в него, <E1>, <E2> ...

Пример документа выглядит как :

<Answers> 

    <Answer ID="1a"> 
    <A1> 
     <E1>Element 1</E1> 
     <E2>Element 2</E2> 
     <E3>Element 3</E3> 
     <E4>Element 4</E4> 
    </A1> 
    <A2> 
     <E1>Element 1</E1> 
     <E2>Element 2</E2> 
     <E3>Element 3</E3> 
     <E4>Element 4</E4> 
    </A2> 
    </Answer> 

    <Answer ID="1b"> 
    <A1> 
     <E1>Element A</E1> 
     <E2>Element B</E2> 
     <E3>Element C</E3> 
    </A1> 
    </Answer> 

    <Answer ID="2"> 
    <A1> 
     <E1>Element 1</E1> 
     <E2>Element 2</E2> 
     <E3>Element 3</E3> 
     <E4>Element 4</E4> 
     <E5>Element 5</E5> 
    </A1> 
    <A2> 
     <E1>Element 1</E1> 
     <E2>Element 2</E2> 
     <E3>Element 3</E3> 
     <E4>Element 4</E4> 
     <E5>Element 5</E5> 
    </A2> 
    <A3> 
     <E1>Element 1</E1> 
     <E2>Element 2</E2> 
     <E3>Element 3</E3> 
     <E4>Element 4</E4> 
     <E5>Element 5</E5> 
    </A3> 

    </Answer> 
</Answers> 

Что входит в Элементы - это любая строка, содержимое не имеет значения, поскольку она не является пустой.

Что нужно для проверки, так это то, что для каждого ответа (обозначается идентификатором) для каждого <A*> существует определенное количество элементов. В этом примере 1а имеет 4 элементов, 1b имеет 3 и 2 имеет 5.

Формат является гибким, так что при необходимости можно изменить положение вещей на что-то вроде: Элемент A Элемент B Элемент C или что-то в этом роде.

Я пробовал всевозможные сочетания с этим, но я не могу найти способ потребовать X количество <E*> в зависимости от идентификатора ответа.

У кого-нибудь есть мысли, или они могут указать мне в правильном направлении, даже если это просто говорит: «Да, XSD может это сделать» или «Нет, XSL не может этого сделать»?

+0

XSLT преобразует документы - это не подтверждает их. Вы можете написать трансформацию, указывающую на элементы, которые не удовлетворяют вашим ограничениям, но вы не можете назвать эту «проверку». Это будет для вас вариант? Если нет, DTD не может этого сделать. Ваши варианты для языков валидации: XML Schema, RelaxNG и Schematron также будут способны к этому (и самому простому!). –

+0

Другой вариант, первый, который появился у меня в голове, - XQuery. – bjimba

+0

DTD не может этого сделать. XSD 1.0 не может этого сделать. XSD 1.1 может делать это с утверждениями. XSLT может это сделать, анализируя идентификатор и подсчитывая дочерние элементы. Итак, заберите свой яд. ;-) – kjhughes

ответ

3

Тип подтверждения, который вы хотите сделать (инструкция «если есть»), называется Утверждение. Как указано в @kjhughes, XML Schema 1.1 имеет утверждения, и вы можете реализовать такие сложные отношения в документе XML с XSD 1.1.

В качестве альтернативы вы можете использовать преобразование XSLT, которое действительно не выполняет проверку, но каким-то образом преобразует ваш входной XML в только те случаи, когда ваши ограничения не выполняются. Тем не менее, XSLT не является языком проверки.

Я предполагаю, что кто-то в конечном итоге внесет ответ XSLT, поэтому я хотел бы предложить что-то еще: Schematron. Следующими правилами Schematron являются утверждения, которые точно определяют необходимые вам ограничения.

<?xml version="1.0" encoding="UTF-8"?> 
<schema xmlns="http://purl.oclc.org/dsdl/schematron" queryBinding="xslt2"> 

    <pattern> 
     <title>Content of the answer element.</title> 
     <rule context="Answer"> 
      <assert test="*[starts-with(name(),'A')]" xml:lang="en">The <name/> element must contain at least 1 A* element.</assert> 
     </rule> 
    </pattern> 

    <pattern> 
     <title>Count number of child elements E* of elements A*</title> 
     <rule context="Answer[@ID = '1a']/*[starts-with(name(),'A')]"> 
      <assert test="count(*[starts-with(name(),'E')]) = 4" xml:lang="en">If the @ID attribute of the Answer element is "1a", 
       then all child elements A* must have exactly 4 child elements E*.</assert> 
     </rule> 
     <rule context="Answer[@ID = '1b']/*[starts-with(name(),'A')]"> 
      <assert test="count(*[starts-with(name(),'E')]) = 3" xml:lang="en">If the @ID attribute of the Answer element is "1b", 
       then all child elements A* must have exactly 3 child elements E*.</assert> 
     </rule> 
     <rule context="Answer[@ID = '2']/*[starts-with(name(),'A')]"> 
      <assert test="count(*[starts-with(name(),'E')]) = 5" xml:lang="en">If the @ID attribute of the Answer element is "2", 
       then all child elements A* must have exactly 5 child elements E*.</assert> 
     </rule> 
    </pattern> 

</schema> 

Если входной документ содержит следующую структуру:

<Answer ID="1a"> 
    <A1> 
     <E1>Element 1</E1> 
     <E2>Element 2</E2> 
     <E4>Element 4</E4> 
    </A1> 
</Answer> 

проверочное приложение будет жаловаться, говоря, что

E [ISO Schematron] If the @ID attribute of the Answer element is "1a", then all child elements A* must have exactly 4 child elements E*. 

Schematron файлы могут быть интерпретированы с Schematron Reference Implementation - с помощью таблицы стилей XSLT - или такие среды, как кислород.


Помимо Примечание: Это не было бы слишком трудно перевести правила SCH выше XSLT, потому что они очень похожи. Вам нужно будет заменить следующее, например:

SCH         | XSLT equivalent 
----------------------------------------------------------------------------- 
<sch:rule context="...">   | <xsl:template match="..."> 
<sch:assert test="*">    | <xsl:if test="not(*)"> 
<sch:report test="*">    | <xsl:if test="*"> 
+0

Спасибо, Матиас ... Глядя на это, он будет работать отлично. Единственная проблема заключается в том, что мой Schematron не вариант с тем, что я пытаюсь, или с моей организацией. В конце концов, это будет XmlDocument в VB.Net, который я хочу проверить перед отправкой в ​​базу данных. Однако похоже, что утверждения - это путь. – neilsimp1

+0

@ neilsimp1 Все, что вам нужно - это процессор XSLT, и поскольку вы упомянули XSLT как возможное решение в своем вопросе, я предположил, что вы можете обрабатывать таблицы стилей XSLT. –