How to create a dtd rule for this XML?

I need to create a dtd rule for not repeating the values of an XML element, in this case, i have a catalog containing 5 songs (name, artist, album, ...), and the name element values can't be repeated, there can't be two song with the same name, my code here:

XML

<?xml version="1.0"?>
<!DOCTYPE catalog SYSTEM "catalog.dtd">
<catalog>
    <song>
    <name>Bed of Roses</name>
    <artist>Bon Jovi</artist>
    <album>Cross Road</album>
    <year>1995</year>
    <genre>Ballad</genre>
    <coments>Good song</coments>
    <path></path>
</song>
<song>
    <name>Fly Away from here</name>
    <artist>Aerosmith</artist>
    <album>Just Push Play</album>
    <year>2001</year>
    <genre>Rock</genre>
    <coments>Good song</coments>
    <path></path>
</song>
</catalog>

DTD
<?xml version="1.0"?>
<!ELEMENT catalog (song)>
<!ELEMENT song (name,artist,album,year,genre,comments,path)>
<!ELEMENT song (name)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT artist (#PCDATA)>
<!ELEMENT album (#PCDATA)>
<!ELEMENT year (#PCDATA)>
<!ELEMENT genre (#PCDATA)>
<!ELEMENT comments (#PCDATA)>

Upvotes: 1

Views: 336

Answers (1)

Daniel Haley
Daniel Haley

Reputation: 52858

What you could do is use a unique ID on the name element. This only gets you half way there though; the ID has to be unique but it doesn't restrict the PCDATA in the name.

To get around this, create text entities to hold the name elements. You can only reference the entity once. If you reference it more than once, you'll get an error similar to:

Attribute value "song1" of type ID must be unique within the document.

This will ensure that the name only gets used once.

Here's an example. (You also had some typos that made your XML/DTD invalid. Those have been fixed.)

catalog.dtd

<!ELEMENT catalog (song+)>
<!ELEMENT song (name,artist,album,year,genre,comments,path)>
<!ELEMENT name (#PCDATA)>
<!ATTLIST name
          id ID #REQUIRED>
<!ELEMENT artist (#PCDATA)>
<!ELEMENT album (#PCDATA)>
<!ELEMENT year (#PCDATA)>
<!ELEMENT genre (#PCDATA)>
<!ELEMENT comments (#PCDATA)>
<!ELEMENT path (#PCDATA)>

<!ENTITY song1 '<name id="song1">Bed of Roses</name>'>
<!ENTITY song2 '<name id="song2">Fly Away from here</name>'>

XML

<!DOCTYPE catalog SYSTEM "catalog.dtd">
<catalog>
    <song>
        &song1;
        <artist>Bon Jovi</artist>
        <album>Cross Road</album>
        <year>1995</year>
        <genre>Ballad</genre>
        <comments>Good song</comments>
        <path></path>
    </song>
    <song>
        &song2;
        <artist>Aerosmith</artist>
        <album>Just Push Play</album>
        <year>2001</year>
        <genre>Rock</genre>
        <comments>Good song</comments>
        <path></path>
    </song>
</catalog>

Disclaimer: I think this is an ugly hack personally. Like mzjn said in the comments, there are other technologies better suited to ensuring this type of constraint.

Upvotes: 2

Related Questions