2013-11-22 7 views
1

Я пытаюсь построить DTD для следующего элемента (как часть большего DTD для полного файла XML):XML DTD опции обязательный атрибут

<contact> 
     <base>019374627</base> 
     <mobile primaryContact="true">0861029388</phone> 
     <email>[email protected]</email> 
</contact> 

Я просто запутался, потому что этого contact элемента должен содержать хотя бы один элемент, и должен быть ровно один элемент внутри contact, который имеет атрибут primaryContact="true".

Как это можно представить с помощью DTD? Любая помощь будет принята с благодарностью!

ответ

2

Это не может быть выражено в DTD.

В DTD вы можете указать, что элемент contact должен содержать элемент mobile. Вы также можете указать, что конкретный подэлемент (например, mobile) должен иметь атрибут primaryContact с фиксированным значением «true».

Но нельзя просто объявить, что элемент должен иметь хотя бы один подэлемент, или что атрибут primaryContact должен происходить только в одном подэлементе. Все разрешенные субэлементы должны быть явно объявлены. Действительность элемента не может зависеть от атрибута, прикрепленного к другому элементу.

FWIW, ограничение может быть выражены в Schematron схемы:

<sch:schema xmlns:sch="http://purl.oclc.org/dsdl/schematron"> 

    <sch:pattern name="Check children of 'contact'"> 
    <sch:rule context="contact"> 
     <sch:assert test="*"> 
     'contact' must contain at least one element 
     </sch:assert> 
     <sch:assert test="count(*[@primaryContact='true']) = 1"> 
     'contact' must contain exactly one element where @primaryContact='true' 
     </sch:assert> 
    </sch:rule> 
    </sch:pattern> 

</sch:schema> 
1

С небольшим изменением вы DTD, вы можете быть в состоянии выразить то, что вам нужно. Идея состоит в том, чтобы обернуть требуемый контент в новый элемент . Это позволяет указать на contact, что он должен иметь один primary элемент:

<contact> 
    <primary><mobile>0861029388</mobile></primary> 
    <base>019374627</base> 
    <email>[email protected]</email> 
</contact> 

Ваш DTD может выглядеть следующим образом:

<!ELEMENT contact (primary, (mobile|base|email)*)> 
<!ELEMENT primary (mobile|base|email)+> 
<!ELEMENT mobile (#PCDATA)> 
<!ELEMENT base (#PCDATA)> 
<!ELEMENT email (#PCDATA)> 

Или, чтобы уменьшить избыточность и увеличить ремонтопригодность:

<!ENTITY % contact_field "mobile|base|email" > 
<!ELEMENT contact (primary, (%contact_field;)*)> 
<!ELEMENT primary (%contact_field;)+> 
<!ELEMENT mobile (#PCDATA)> 
<!ELEMENT base (#PCDATA)> 
<!ELEMENT email (#PCDATA)> 
Смежные вопросы