commit:     6ef11f64a2d763360542bd6a3c74da46f15dfa23
Author:     Ulrich Müller <ulm <AT> gentoo <DOT> org>
AuthorDate: Sun Jan 16 21:59:15 2022 +0000
Commit:     Ulrich Müller <ulm <AT> gentoo <DOT> org>
CommitDate: Mon Jan 24 18:16:10 2022 +0000
URL:        https://gitweb.gentoo.org/proj/devmanual.git/commit/?id=6ef11f64

devbook.rnc: Change from DTD to RELAX NG compact schema

The currently used DTD format has several limitations. It does not
support data types, and it is not expressive enough for some element
syntax used in the devmanual. For example, it cannot accurately
describe the uri element which comes in two alternative forms
(namely, with the link in its body text or as an attribute).

RELAX NG is chosen because it has a variant with a compact and very
readable non-XML syntax, and it is well supported both as an input and
as an output format by conversion tools like app-text/trang. Also, we
need RNC for app-emacs/nxml-gentoo-schemas anyway.

devbook.rnc is the source file, but the generated devbook.rng is also
committed to the repository, in order to avoid an additional
dependency on trang or rnc2rng.

Signed-off-by: Ulrich Müller <ulm <AT> gentoo.org>

 Makefile    |  10 +-
 devbook.dtd |  94 ---------------
 devbook.rnc | 113 ++++++++++++++++++
 devbook.rng | 391 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 512 insertions(+), 96 deletions(-)

diff --git a/Makefile b/Makefile
index 2c7952a..cbb31e7 100644
--- a/Makefile
+++ b/Makefile
@@ -82,10 +82,16 @@ install: all
          install -m 644 $(JS_FILES) "$(DESTDIR)$(htmldir)"/; \
        fi
 
-validate:
-       @xmllint --noout --dtdvalid devbook.dtd $(XMLS)
+# Not all versions of xmllint support --quiet, so test for it first
+validate: devbook.rng
+       @opt=--quiet; xmllint --help 2>&1 | grep -q -- --quiet || opt=; \
+       xmllint --noout $${opt} --relaxng $< $(XMLS)
        @echo "xmllint validation successful"
 
+%.rng: %.rnc
+       trang $< $@
+       sed -i -e '2s/^/<!-- Auto-generated from $<; do not edit! -->\n/' $@
+
 # Run app-text/htmltidy on the output to detect mistakes.
 # We have to loop through them because otherwise tidy won't
 # tell you which file contains a mistake.

diff --git a/devbook.dtd b/devbook.dtd
deleted file mode 100644
index 77ba737..0000000
--- a/devbook.dtd
+++ /dev/null
@@ -1,94 +0,0 @@
-<!-- Copyright 2019-2021 Gentoo Authors -->
-<!-- Distributed under the terms of the MIT/X11 license
-     or the CC-BY-SA-4.0 license (dual-licensed) -->
-
-<!-- Document Type Definition for the Gentoo Devmanual -->
-<!-- Based on common.dtd from GuideXML -->
-
-<!ENTITY  % block.class     "p|pre|codesample|note|important|warning|todo
-                                |figure|table|ul|ol|dl">
-<!ENTITY  % attrib.class    "b|c|e">
-<!ENTITY  % inline.class    "%attrib.class;|d|uri">
-<!ENTITY  % all.class       "%block.class;|%inline.class;">
-
-<!ELEMENT guide         (chapter, include*)>
-<!ATTLIST guide         root (true) #IMPLIED
-                        self CDATA #IMPLIED>
-
-<!ELEMENT include       EMPTY>
-<!ATTLIST include       href CDATA #REQUIRED>
-
-<!ELEMENT chapter       (title, (body|section), section*)>
-<!ELEMENT section       (title, (body|subsection), subsection*)>
-<!ELEMENT subsection    (title, (body|subsubsection), subsubsection*)>
-<!ELEMENT subsubsection (title, body)>
-
-<!-- Title texts are used as anchors, so allow only text attributes -->
-<!ELEMENT title         (#PCDATA|%attrib.class;)*>
-
-<!ELEMENT body          (authors|contentsTree|%block.class;)+>
-
-<!ELEMENT authors       (author+|authorlist+)>
-<!ELEMENT author        (#PCDATA|%inline.class;)*>
-<!ATTLIST author        name  CDATA #REQUIRED
-                        email CDATA #IMPLIED>
-<!ELEMENT authorlist    EMPTY>
-<!ATTLIST authorlist    title CDATA #REQUIRED
-                        href  CDATA #REQUIRED>
-
-<!ELEMENT contentsTree  EMPTY>
-<!ATTLIST contentsTree  maxdepth   CDATA #IMPLIED
-                        root       CDATA #IMPLIED
-                        extraction CDATA #IMPLIED>
-
-<!ELEMENT p             (#PCDATA|%inline.class;)*>
-
-<!ELEMENT pre           (#PCDATA)>
-
-<!ELEMENT codesample    (#PCDATA)>
-<!ATTLIST codesample    lang (c|ebuild|make|m4|sgml) #REQUIRED
-                        numbering (lines) #IMPLIED>
-
-<!ELEMENT note          (#PCDATA|%inline.class;)*>
-<!ELEMENT important     (#PCDATA|%inline.class;)*>
-<!ELEMENT warning       (#PCDATA|%inline.class;)*>
-<!ELEMENT todo          (#PCDATA|%inline.class;)*>
-
-<!ELEMENT figure        EMPTY>
-<!ATTLIST figure        link CDATA #REQUIRED
-                        short CDATA #IMPLIED
-                        caption CDATA #IMPLIED>
-
-<!ELEMENT table         (tr)+>
-
-<!ELEMENT tr            (th|ti)+>
-
-<!ELEMENT th            (#PCDATA|%inline.class;)*>
-<!ATTLIST th            colspan CDATA #IMPLIED
-                        rowspan CDATA #IMPLIED
-                        align (left|center|right) "left">
-
-<!ELEMENT ti            (#PCDATA|%all.class;)*>
-<!ATTLIST ti            colspan CDATA #IMPLIED
-                        rowspan CDATA #IMPLIED
-                        nowrap  CDATA #IMPLIED
-                        align (left|center|right) "left">
-
-<!ELEMENT ul            (li)+>
-<!ATTLIST ul            class CDATA #IMPLIED>
-
-<!ELEMENT ol            (li)+>
-
-<!ELEMENT li            (#PCDATA|%all.class;)*>
-
-<!ELEMENT dl            (dt|dd)+>
-<!ELEMENT dt            (#PCDATA|%inline.class;)*>
-<!ELEMENT dd            (#PCDATA|%all.class;)*>
-
-<!ELEMENT b             (#PCDATA|%inline.class;)*>
-<!ELEMENT c             (#PCDATA|%inline.class;)*>
-<!ELEMENT e             (#PCDATA|%inline.class;)*>
-<!ELEMENT d             EMPTY>
-
-<!ELEMENT uri           (#PCDATA|%inline.class;)*>
-<!ATTLIST uri           link CDATA #IMPLIED>

diff --git a/devbook.rnc b/devbook.rnc
new file mode 100644
index 0000000..4ca931d
--- /dev/null
+++ b/devbook.rnc
@@ -0,0 +1,113 @@
+# Copyright 2022 Gentoo Authors
+# Distributed under the terms of the MIT license
+# or the CC-BY-SA-4.0 license (dual-licensed)
+
+# RELAX NG schema for the Gentoo Devmanual
+# Based on common.dtd from GuideXML
+
+block.class = p | pre | codesample | note | important | warning | todo
+| figure | table | ul | ol | dl
+attrib.class = text | b | c | e
+inline.class = attrib.class | d | uri
+
+attrib = attrib.class*
+inline = inline.class*
+all = (block.class | inline.class)*
+
+start = guide
+
+guide = element guide {
+  (attribute root { "true" } | attribute self { text }),
+  chapter,
+  \include*
+}
+
+\include = element include { attribute href { text } }
+
+chapter = element chapter { title, (body | section), section* }
+section = element section { title, (body | subsection), subsection* }
+subsection =
+  element subsection { title, (body | subsubsection), subsubsection* }
+subsubsection = element subsubsection { title, body }
+
+# Title texts are used as anchors, so allow only text attributes
+title = element title { attrib }
+
+body = element body { (authors | contentsTree | block.class)+ }
+
+authors = element authors { author+ | authorlist+ }
+
+author = element author {
+  attribute name { text },
+  attribute email { text }?,
+  inline
+}
+
+authorlist = element authorlist {
+  attribute title { text },
+  attribute href { text }
+}
+
+contentsTree = element contentsTree {
+  attribute maxdepth { xsd:unsignedInt }?,
+  attribute root { text }?,
+  attribute extraction { text }?
+}
+
+p = element p { inline }
+
+pre = element pre { text }
+
+codesample = element codesample {
+  attribute lang { "c" | "ebuild" | "make" | "m4" | "sgml" },
+  attribute numbering { "lines" }?,
+  text
+}
+
+note = element note { inline }
+important = element important { inline }
+warning = element warning { inline }
+todo = element todo { inline }
+
+figure = element figure {
+  attribute link { text },
+  attribute short { text }?,
+  attribute caption { text }?
+}
+
+table = element table { tr+ }
+tr = element tr { (th | ti)+ }
+
+th = element th {
+  attribute colspan { xsd:unsignedInt }?,
+  attribute rowspan { xsd:unsignedInt }?,
+  attribute align { "left" | "center" | "right" }?,
+  inline
+}
+
+ti = element ti {
+  attribute colspan { xsd:unsignedInt }?,
+  attribute rowspan { xsd:unsignedInt }?,
+  attribute nowrap { "nowrap" }?,
+  attribute align { "left" | "center" | "right" }?,
+  all
+}
+
+ul = element ul { attribute class { "list-group" }?, li+ }
+ol = element ol { li+ }
+li = element li { all }
+
+dl = element dl { (dt | dd)+ }
+dt = element dt { inline }
+dd = element dd { all }
+
+b = element b { inline }
+c = element c { inline }
+e = element e { inline }
+d = element d { empty }
+
+uri = element uri {
+  # uri can have either an URI in the body text or a link attribute
+  xsd:anyURI
+  | (attribute link { text }, inline)
+}

diff --git a/devbook.rng b/devbook.rng
new file mode 100644
index 0000000..660e4d2
--- /dev/null
+++ b/devbook.rng
@@ -0,0 +1,391 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Auto-generated from devbook.rnc; do not edit! -->
+<grammar xmlns="http://relaxng.org/ns/structure/1.0"; 
datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes";>
+  <!--
+    Copyright 2022 Gentoo Authors
+    Distributed under the terms of the MIT license
+    or the CC-BY-SA-4.0 license (dual-licensed)
+  -->
+  <!--
+    RELAX NG schema for the Gentoo Devmanual
+    Based on common.dtd from GuideXML
+  -->
+  <define name="block.class">
+    <choice>
+      <ref name="p"/>
+      <ref name="pre"/>
+      <ref name="codesample"/>
+      <ref name="note"/>
+      <ref name="important"/>
+      <ref name="warning"/>
+      <ref name="todo"/>
+      <ref name="figure"/>
+      <ref name="table"/>
+      <ref name="ul"/>
+      <ref name="ol"/>
+      <ref name="dl"/>
+    </choice>
+  </define>
+  <define name="attrib.class">
+    <choice>
+      <text/>
+      <ref name="b"/>
+      <ref name="c"/>
+      <ref name="e"/>
+    </choice>
+  </define>
+  <define name="inline.class">
+    <choice>
+      <ref name="attrib.class"/>
+      <ref name="d"/>
+      <ref name="uri"/>
+    </choice>
+  </define>
+  <define name="attrib">
+    <zeroOrMore>
+      <ref name="attrib.class"/>
+    </zeroOrMore>
+  </define>
+  <define name="inline">
+    <zeroOrMore>
+      <ref name="inline.class"/>
+    </zeroOrMore>
+  </define>
+  <define name="all">
+    <zeroOrMore>
+      <choice>
+        <ref name="block.class"/>
+        <ref name="inline.class"/>
+      </choice>
+    </zeroOrMore>
+  </define>
+  <start>
+    <ref name="guide"/>
+  </start>
+  <define name="guide">
+    <element name="guide">
+      <choice>
+        <attribute name="root">
+          <value>true</value>
+        </attribute>
+        <attribute name="self"/>
+      </choice>
+      <ref name="chapter"/>
+      <zeroOrMore>
+        <ref name="include"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <define name="include">
+    <element name="include">
+      <attribute name="href"/>
+    </element>
+  </define>
+  <define name="chapter">
+    <element name="chapter">
+      <ref name="title"/>
+      <choice>
+        <ref name="body"/>
+        <ref name="section"/>
+      </choice>
+      <zeroOrMore>
+        <ref name="section"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <define name="section">
+    <element name="section">
+      <ref name="title"/>
+      <choice>
+        <ref name="body"/>
+        <ref name="subsection"/>
+      </choice>
+      <zeroOrMore>
+        <ref name="subsection"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <define name="subsection">
+    <element name="subsection">
+      <ref name="title"/>
+      <choice>
+        <ref name="body"/>
+        <ref name="subsubsection"/>
+      </choice>
+      <zeroOrMore>
+        <ref name="subsubsection"/>
+      </zeroOrMore>
+    </element>
+  </define>
+  <define name="subsubsection">
+    <element name="subsubsection">
+      <ref name="title"/>
+      <ref name="body"/>
+    </element>
+  </define>
+  <!-- Title texts are used as anchors, so allow only text attributes -->
+  <define name="title">
+    <element name="title">
+      <ref name="attrib"/>
+    </element>
+  </define>
+  <define name="body">
+    <element name="body">
+      <oneOrMore>
+        <choice>
+          <ref name="authors"/>
+          <ref name="contentsTree"/>
+          <ref name="block.class"/>
+        </choice>
+      </oneOrMore>
+    </element>
+  </define>
+  <define name="authors">
+    <element name="authors">
+      <choice>
+        <oneOrMore>
+          <ref name="author"/>
+        </oneOrMore>
+        <oneOrMore>
+          <ref name="authorlist"/>
+        </oneOrMore>
+      </choice>
+    </element>
+  </define>
+  <define name="author">
+    <element name="author">
+      <attribute name="name"/>
+      <optional>
+        <attribute name="email"/>
+      </optional>
+      <ref name="inline"/>
+    </element>
+  </define>
+  <define name="authorlist">
+    <element name="authorlist">
+      <attribute name="title"/>
+      <attribute name="href"/>
+    </element>
+  </define>
+  <define name="contentsTree">
+    <element name="contentsTree">
+      <optional>
+        <attribute name="maxdepth">
+          <data type="unsignedInt"/>
+        </attribute>
+      </optional>
+      <optional>
+        <attribute name="root"/>
+      </optional>
+      <optional>
+        <attribute name="extraction"/>
+      </optional>
+    </element>
+  </define>
+  <define name="p">
+    <element name="p">
+      <ref name="inline"/>
+    </element>
+  </define>
+  <define name="pre">
+    <element name="pre">
+      <text/>
+    </element>
+  </define>
+  <define name="codesample">
+    <element name="codesample">
+      <attribute name="lang">
+        <choice>
+          <value>c</value>
+          <value>ebuild</value>
+          <value>make</value>
+          <value>m4</value>
+          <value>sgml</value>
+        </choice>
+      </attribute>
+      <optional>
+        <attribute name="numbering">
+          <value>lines</value>
+        </attribute>
+      </optional>
+      <text/>
+    </element>
+  </define>
+  <define name="note">
+    <element name="note">
+      <ref name="inline"/>
+    </element>
+  </define>
+  <define name="important">
+    <element name="important">
+      <ref name="inline"/>
+    </element>
+  </define>
+  <define name="warning">
+    <element name="warning">
+      <ref name="inline"/>
+    </element>
+  </define>
+  <define name="todo">
+    <element name="todo">
+      <ref name="inline"/>
+    </element>
+  </define>
+  <define name="figure">
+    <element name="figure">
+      <attribute name="link"/>
+      <optional>
+        <attribute name="short"/>
+      </optional>
+      <optional>
+        <attribute name="caption"/>
+      </optional>
+    </element>
+  </define>
+  <define name="table">
+    <element name="table">
+      <oneOrMore>
+        <ref name="tr"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <define name="tr">
+    <element name="tr">
+      <oneOrMore>
+        <choice>
+          <ref name="th"/>
+          <ref name="ti"/>
+        </choice>
+      </oneOrMore>
+    </element>
+  </define>
+  <define name="th">
+    <element name="th">
+      <optional>
+        <attribute name="colspan">
+          <data type="unsignedInt"/>
+        </attribute>
+      </optional>
+      <optional>
+        <attribute name="rowspan">
+          <data type="unsignedInt"/>
+        </attribute>
+      </optional>
+      <optional>
+        <attribute name="align">
+          <choice>
+            <value>left</value>
+            <value>center</value>
+            <value>right</value>
+          </choice>
+        </attribute>
+      </optional>
+      <ref name="inline"/>
+    </element>
+  </define>
+  <define name="ti">
+    <element name="ti">
+      <optional>
+        <attribute name="colspan">
+          <data type="unsignedInt"/>
+        </attribute>
+      </optional>
+      <optional>
+        <attribute name="rowspan">
+          <data type="unsignedInt"/>
+        </attribute>
+      </optional>
+      <optional>
+        <attribute name="nowrap">
+          <value>nowrap</value>
+        </attribute>
+      </optional>
+      <optional>
+        <attribute name="align">
+          <choice>
+            <value>left</value>
+            <value>center</value>
+            <value>right</value>
+          </choice>
+        </attribute>
+      </optional>
+      <ref name="all"/>
+    </element>
+  </define>
+  <define name="ul">
+    <element name="ul">
+      <optional>
+        <attribute name="class">
+          <value>list-group</value>
+        </attribute>
+      </optional>
+      <oneOrMore>
+        <ref name="li"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <define name="ol">
+    <element name="ol">
+      <oneOrMore>
+        <ref name="li"/>
+      </oneOrMore>
+    </element>
+  </define>
+  <define name="li">
+    <element name="li">
+      <ref name="all"/>
+    </element>
+  </define>
+  <define name="dl">
+    <element name="dl">
+      <oneOrMore>
+        <choice>
+          <ref name="dt"/>
+          <ref name="dd"/>
+        </choice>
+      </oneOrMore>
+    </element>
+  </define>
+  <define name="dt">
+    <element name="dt">
+      <ref name="inline"/>
+    </element>
+  </define>
+  <define name="dd">
+    <element name="dd">
+      <ref name="all"/>
+    </element>
+  </define>
+  <define name="b">
+    <element name="b">
+      <ref name="inline"/>
+    </element>
+  </define>
+  <define name="c">
+    <element name="c">
+      <ref name="inline"/>
+    </element>
+  </define>
+  <define name="e">
+    <element name="e">
+      <ref name="inline"/>
+    </element>
+  </define>
+  <define name="d">
+    <element name="d">
+      <empty/>
+    </element>
+  </define>
+  <define name="uri">
+    <element name="uri">
+      <choice>
+        <!-- uri can have either an URI in the body text or a link attribute 
-->
+        <data type="anyURI"/>
+        <group>
+          <attribute name="link"/>
+          <ref name="inline"/>
+        </group>
+      </choice>
+    </element>
+  </define>
+</grammar>

Reply via email to