24

I have a local DTD file test.dtd. Content is :

<!DOCTYPE coord [
<!ELEMENT coord (date)>
<!ELEMENT date (#PCDATA)>
]>

I'd like to validate an XML using xmllint. This XML has no DOCTYPE in it :

<?xml version="1.0" encoding="x-mac-roman"?>
<coord>
    <date>20150312</date>
</coord>

No problem if I insert the DTD block as a 2nd line into a copy of my XML file and use:

xmllint --valid --noout my2.xml

But when I try :

xmllint --loaddtd test.dtd --valid --noout my.xml

xmllint --dtdvalid test.dtd --noout my.xml

both don't work. The outout is :

test.dtd:1: parser error : Content error in the external subset
<!DOCTYPE coord [
^
test.dtd:1: parser error : Content error in the external subset
<!DOCTYPE coord [
^
Could not parse DTD test.dtd

Any idea ? It seems that my XML MUST contain a DOCTYPE line (with SYSTEM keyword) to reference the external DOCTYPE file, that I want to avoid. See : http://www.w3schools.com/dtd/

Is there any solution without modifying the XML ?

Eric H.
  • 2,152
  • 4
  • 22
  • 34

1 Answers1

32

First of all, external DTDs do not need the <!DOCTYPE preamble - remove it from the DTD file:

<!ELEMENT coord (date)>
<!ELEMENT date (#PCDATA)>

Then, --loaddtd fetches an external DTD, which is not the same as validating against an external DTD. Use the --dtdvalid option as follows:

$ xmllint --noout --dtdvalid test.dtd test.xml

If the XML document is valid, xmllint will not output anything (because of --noout). If you change the DTD to, say:

<!ELEMENT coord (date,other)>
<!ELEMENT date (#PCDATA)>

The output will be

$ xmllint --noout --dtdvalid test.dtd test.xml
test.xml:2: element coord: validity error : Element coord content does not follow the DTD, expecting (date , other), got (date )
Document test.xml does not validate against test.dtd

Look for more information on the doc pages of NMT or XMLSoft.

Mathias Müller
  • 22,203
  • 13
  • 58
  • 75
  • Thanks. But nothing says that "coord" is the root element. – Eric H. Mar 16 '15 at 10:01
  • 1
    @EricH. If you think about it, you don't need to know which element is the root. The important thing is that you, the author of the DTD, know which element is the root element, and write a rule for it. xmllint starts parsing an XML document at the root, so this rule will be the first to be applied anyway. – Mathias Müller Mar 16 '15 at 10:12
  • Working for me. xmllint --noout --dtdvalid test.dtd test.xml – JeanCarlos Chavarria Jun 27 '19 at 18:04