【问题标题】:How to create a dtd rule for this XML?如何为此 XML 创建 dtd 规则?
【发布时间】:2015-03-10 23:55:37
【问题描述】:

我需要创建一个不重复 XML 元素值的 dtd 规则,在这种情况下,我有一个包含 5 首歌曲(名称、艺术家、专辑...)的目录,并且名称元素值可以'不能重复,不能有两首歌同名,我的代码在这里:

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)>

【问题讨论】:

  • 这是不可能的。 DTD 无法表达您需要的约束类型(确保某些元素的唯一值)。您必须使用其他一些技术,例如Schematron
  • 我的网络老师要我这样做
  • @mzjn - 这在技术上是可行的(参见下面的丑陋黑客),但我同意有更好的技术来确保这种类型的约束。

标签: xml dtd


【解决方案1】:

可以做的是在name 元素上使用唯一ID。不过,这只能让你成功一半; ID 必须是唯一的,但它不会限制name 中的 PCDATA。

要解决这个问题,请创建文本实体来保存名称元素。您只能引用该实体一次。如果你多次引用它,你会得到一个类似的错误:

类型 ID 的属性值“song1”在文档中必须是唯一的。

这将确保该名称只被使用一次。

这是一个例子。 (您还有一些拼写错误导致您的 XML/DTD 无效。这些错误已得到修复。)

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>

免责声明:我个人认为这是一个丑陋的黑客行为。就像 mzjn 在 cmets 中所说的那样,还有其他技术更适合确保这种类型的约束。

【讨论】:

  • 利用 ID 的唯一性是可行的,但这并不限制元素内容。将“玫瑰之床”作为两首歌曲的名称不会导致错误。确实是丑陋的黑客。但是很有创意。值得一票。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-02-06
  • 1970-01-01
  • 2012-01-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-15
相关资源
最近更新 更多