XML, DTD: how to make the order not important
I started off using an XML file and a parser as a convenient way to store my data
I want to use DTD to check the structure of the xml files when they arrive.
Here is my DTD file
< ?xml version="1.0" encoding="UTF-8"?>
< !ELEMENT document (level*)>
< !ELEMENT level (file,filelName?,fileNumber?)>
< !ELEMENT file (#PCDATA)>
< !ELEMENT filelName (#PCDATA)>
< !ELEMENT fileNumber (#PCDATA)>
(note that fileName and fileNumber are actually purely optional)
and
<document>
<level>
<file>group1file01</file>
</level>
<level>
<file>group1file02</file>
<fileName>file 2</fileName>
<fileNumber>0</fileNumber>
</level>
...
as such all this works fine. (I use eclipse "validate" option to test it for now)
however while testing I got what I think is a wierd error
if I do
<level>
<levelName>Level 2</levelName>
<levelNumber>0</levelNumber>
<file>group1level02</file>
</level>
changing the order of the lines, Eclipse refuses to validate it ...
I was w开发者_C百科ondering if this was a problem with Eclipse or if the order is actually important.
If the order is important how can I change the DTD to make it work no matter the ordering of he elements?
I can't really change the XML because I already have all the XML files and the parser written (I know I did it the wrong way round lol).
As Roger said, there are only ordered lists, but you can use operator OR |
to define all accepted combinations
<!ELEMENT level ((file,filelName?,fileNumber?)|(filelName?,fileNumber?,file))>
Look here, there is an example in the section Choices
Declaring unordered lists with occurrence constraints in DTD will often result in long or complicated looking declarations. One big reason for this is that DTDs must be deterministic, therefore even switching to XML Schemas don't necessarily help.
Here is a DTD declaration for element <level>
that contains:
- exactly 1
<file>
element - 0-1
<fileName>
elements - 0-1
<fileNumber>
elements - in any possible order
code:
<!ELEMENT level ( (file, ((fileName, fileNumber?) | (fileNumber, fileName?))?)
|(fileName, ((file, fileNumber?) | (fileNumber, file)))
|(fileNumber, ((file, fileName?) | (fileName, file))) )>
You can use ANY
keyword if you don't bother too much about validity:
<!ELEMENT level ANY>
I have faced a similar problem here, this two cases may appear:
<Instructors>
<Lecturer>
</Lecturer>
<Professor>
</Professor>
</Instructors>
<Instructors>
<Lecturer>
</Lecturer>
<Professor>
</Professor>
</Instructors>
The only solution I found was this:
<!ELEMENT Instructors ANY>
Maybe there are a better solution, but it works fine for my particular problem.
With a DTD the child nodes have to appear in the order listed in the element definition. There is no way to allow for alternative orderings, unless you want to upgrade to an XSD schema.
Addendum: Per @Gaim, you can offer alternative orders using the (a,b,c...)|(b,a,c...) syntax, but this is not really practical for more than, say, 3 nested elements, since an arbitrary order allows for a factorial number of orderings -- 6 for 3 elements, 24 for 4 elements, 120 for 5 elements -- and clever use of ? operators is sure to result in false validation for strange cases.
If you can guess sensible upper-bound for the number of children for your element, than there is extremely dirty way how to overcome the problem. Follows the example for 0-3 children:
<!ELEMENT myUnorderedElement ( (option1 | option2 | option3)?, (option1 | option2 | option3)?, (option1 | option2 | option3)? >
Thus, you allow the element "myUnorderedElement" to have 0-3 children of any of type option1, option2 or option3.
精彩评论