Search code examples
xmlvalidationdtdw3cw3c-validation

XML - How Can I Add a Second Entry?


I want to try and add a second entry to my XML file, however, upon adding another entry I get an error on the validator

Code: Here is my DTD:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!DOCTYPE car [

    <!ELEMENT car (make, model, year, colour, engine, accessories)>

    <!ELEMENT make (#PCDATA)>
    <!ELEMENT model (#PCDATA)>
    <!ELEMENT year (#PCDATA)>
    <!ELEMENT colour (#PCDATA)>
    <!ELEMENT engine (number_of_cylinders, fuel_system)>
    <!ELEMENT number_of_cylinders (#PCDATA)>
    <!ELEMENT fuel_system (#PCDATA|carburetted|fueld-injected)*>
    <!ELEMENT accessories EMPTY>
        <!ATTLIST accessories radio (yes|no) #REQUIRED>
        <!ATTLIST accessories air_conditioning (yes|no) #REQUIRED>
        <!ATTLIST accessories power_steering (yes|no) #REQUIRED>
]>

XML Entry:

<car>
    <make>Ford</make>
    <model>001</model>
    <year>2014</year>
    <colour>black</colour>
    <engine> <number_of_cylinders>3</number_of_cylinders> <fuel_system>"carburetted"</fuel_system></engine>
    <accessories radio="yes" air_conditioning="yes" power_steering="yes"/>
</car>

Solution

  • You're only allowed to have one root element, so you're going to need to add another element that can contain multiple car elements.

    Something like:

    <!ELEMENT cars (car+)>
    

    I noticed a couple of other things too.

    1. It seems like you're confusing internal and external subsets. You're not allowed to have a doctype declaration in an external subset. In the example you gave that should all be one file. If the DTD is in a separate file, move the doctype declaration from the DTD to the XML instance and reference the DTD.

    2. You can simplify your attribute declarations by only using 1 per element.

    3. You reference the elements carburetted and fueld-injected, but don't declare them. It looks like you actually want the option of 2 values. You can't do that with DTD so you'll have to make an attribute with the enumerations.

    Here are a couple of examples that show:

    • the internal subset
    • the external subset
    • the extra element references converted to type attribute
    • the attribute declaration simplification
    • the addition of the cars element

    Internal Subset Example

    cars.xml

    <!DOCTYPE cars [
    
    <!ELEMENT cars (car+)>
    
    <!ELEMENT car (make, model, year, colour, engine, accessories)>
    
    <!ELEMENT make (#PCDATA)>
    <!ELEMENT model (#PCDATA)>
    <!ELEMENT year (#PCDATA)>
    <!ELEMENT colour (#PCDATA)>
    <!ELEMENT engine (number_of_cylinders, fuel_system)>
    <!ELEMENT number_of_cylinders (#PCDATA)>
    <!ELEMENT fuel_system EMPTY>
    <!ATTLIST fuel_system
              type (carburetted|fuel-injected) #REQUIRED>
    <!ELEMENT accessories EMPTY>
    <!ATTLIST accessories 
              radio            (yes|no) #REQUIRED
              air_conditioning (yes|no) #REQUIRED
              power_steering   (yes|no) #REQUIRED>
    ]>
    <cars>
        <car>
            <make>Ford</make>
            <model>001</model>
            <year>2014</year>
            <colour>black</colour>
            <engine> 
                <number_of_cylinders>3</number_of_cylinders> 
                <fuel_system type="carburetted"/>
            </engine>
            <accessories radio="yes" air_conditioning="yes" power_steering="yes"/>
        </car>
    </cars>
    

    External Subset Example

    cars.dtd

    <!ELEMENT cars (car+)>
    
    <!ELEMENT car (make, model, year, colour, engine, accessories)>
    
    <!ELEMENT make (#PCDATA)>
    <!ELEMENT model (#PCDATA)>
    <!ELEMENT year (#PCDATA)>
    <!ELEMENT colour (#PCDATA)>
    <!ELEMENT engine (number_of_cylinders, fuel_system)>
    <!ELEMENT number_of_cylinders (#PCDATA)>
    <!ELEMENT fuel_system EMPTY>
    <!ATTLIST fuel_system
              type (carburetted|fuel-injected) #REQUIRED>
    <!ELEMENT accessories EMPTY>
    <!ATTLIST accessories 
              radio            (yes|no) #REQUIRED
              air_conditioning (yes|no) #REQUIRED
              power_steering   (yes|no) #REQUIRED>
    

    cars.xml

    <!DOCTYPE cars SYSTEM "cars.dtd">
    <cars>
        <car>
            <make>Ford</make>
            <model>001</model>
            <year>2014</year>
            <colour>black</colour>
            <engine> 
                <number_of_cylinders>3</number_of_cylinders> 
                <fuel_system type="carburetted"/>
            </engine>
            <accessories radio="yes" air_conditioning="yes" power_steering="yes"/>
        </car>
    </cars>