XML et les DTD

Je me suis mis en tête de développer un outil qui génère une interface utilisateur à partir d’un fichier XML, je connais déjà SAX pour parser un fichier XML mais je n’ai jamais créer un “type” de fichier XML et son DTD.
Après quelques recherches sur Google, je rentre bredouille et je galère donc à créer ce fameux fichier DTD. Quelqu’un a-t-il des resources sur le format XML genre “XML for dummies” ? mais le plus exaustif possible.

Et tant que j’y suis voici le problème que je rencontre,

Mon DTD actuel
[codebox]

[/codebox]

Et le message d’insulte qui va avec
[codebox]
org.xml.sax.SAXParseException: A ‘(’ character or an element type is required in the declaration of element type “screenonthefly”.
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseExcept
ion(ErrorHandlerWrapper.java:195)
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.fatalError(ErrorHand
lerWrapper.java:174)
at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorRep
orter.java:388)
at com.sun.org.apache.xerces.internal.impl.XMLScanner.reportFatalError(XMLScanner.j
ava:1411)
at com.sun.org.apache.xerces.internal.impl.XMLDTDScannerImpl.scanElementDecl(XMLDTD
ScannerImpl.java:890)
at com.sun.org.apache.xerces.internal.impl.XMLDTDScannerImpl.scanDecls(XMLDTDScanne
rImpl.java:1980)
at com.sun.org.apache.xerces.internal.impl.XMLDTDScannerImpl.scanDTDExternalSubset(
XMLDTDScannerImpl.java:320)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$DTDDriver.dispatch(XMLDocumentScannerImpl.java:1185)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$DTDDriver.next(XMLDocumentScannerImpl.java:1075)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$PrologDriver.next(XMLDocumentScannerImpl.java:993)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentS
cannerImpl.java:647)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocum
ent(XMLDocumentFragmentScannerImpl.java:508)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configu
ration.java:807)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configu
ration.java:737)
at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:107)
at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXPa
rser.java:1205)
at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:522)
at javax.xml.parsers.SAXParser.parse(SAXParser.java:395)
at javax.xml.parsers.SAXParser.parse(SAXParser.java:198)
at org.eucalyptus.erp.swing.onthefly.OnTheFlyPanelFactory.buildOnTheFlyPanel(OnTheF
lyPanelFactory.java:44)
at org.eucalyptus.erp.swing.onthefly.OnTheFlyPanelFactoryTest.testBuildOnTheFlyPane
l(OnTheFlyPanelFactoryTest.java:33)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.jav
a:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at junit.framework.TestCase.runTest(TestCase.java:168)
at junit.framework.TestCase.runBare(TestCase.java:134)
at junit.framework.TestResult$1.protect(TestResult.java:110)
at junit.framework.TestResult.runProtected(TestResult.java:128)
at junit.framework.TestResult.run(TestResult.java:113)
at junit.framework.TestCase.run(TestCase.java:124)
at junit.framework.TestSuite.runTest(TestSuite.java:232)
at junit.framework.TestSuite.run(TestSuite.java:227)
at org.junit.internal.runners.OldTestClassRunner.run(OldTestClassRunner.java:76)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReferen
ce.java:38)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner
.java:460)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner
.java:673)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java
:386)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.jav
a:196)
[/codebox]

Hop rapidement un petit lien sur les XML : http://xml.developpez.com/cours/.

Edit (piaf) :
Bon en étant un poil plus précis : http://haypo.developpez.com/tutoriel/xml/introduction/, un truc qui m’avais bien servi en licence, à défaut d’un prof moisi.
http://zvon.developpez.com/tutoriels/dtd/ : la dtd par l’exemple.

Sinon Glade te permet d’exporter au format xml une interface:
http://www.gotmono.com/docs/gnome/bindings/glade/glade.html

(si le but est de définir une interface en xml et pas de résoudre un prob. de dtd, évidemment)

Et tu as vraiment besoin de DTD ? Parce que les XML Schema c’est quand même un peu plus friendly que les DTD et couvrent un besoin plus large. J’y connais pas grand chose, mais les DTD clairement ça fait flipper alors que les XSL sont légèrement plus sympas.

[quote=« nolan, post:3, topic: 47038 »]Sinon Glade te permet d’exporter au format xml une interface:
http://www.gotmono.com/docs/gnome/bindings/glade/glade.html

(si le but est de définir une interface en xml et pas de résoudre un prob. de dtd, évidemment)[/quote]

Je ne cherche pas à faire du GTK mais du Swing.

Je ne connais pas du tout XML Schema, ça sert à quoi ? Je penssai que pour décrire la syntaxe de ton fichier XML, il fallait automatiquement passé par un DTD.

http://fr.wikipedia.org/wiki/XSD :slight_smile:
Je te recommande aussi de faire du xsd, c’est plus about que les dtd.

Bon courage pour ton générateur, m’est avis que tu vas en chier :crying:

Pour ce que tu veux faire, je te conseille de regarder du côté de XSLT (XSL Transform). C’est un langage de transformation de XML. Tu pourrais très facilement envisager de générer le code du GUI à partir du XML Schéma (XSD). Il me semble même qu’il y a des extensions assez puissantes à XSLT en Java (Saxon ou un truc comme ça)

Après vos remarques et mes quelques recherches rapides sur Google/Wikipedia, je part du XSD, merci de m’avoir réorienté sur la bonne voie (c’est ce que j’aime sur la geekzone).

Pour la transformation XSLT, c’est une solution que je n’avais pas envisagé, à voir si c’est plus simple que de créer un parser… J’essaierai peut-être de faire 2 prototypes (XSD + Parser SAX).

Merci beaucoup en tout cas pour vos commentaires constructifs.

Voici la version corrigée du DTD.
Le message signifiait qu’il fallait des parenthèses autour des descendants des éléments.
J’ai aussi ajouté des EMPTY pour les éléments sans descendants.
Il manquait aussi un ‘D’ à un REQUIRED.
Et attention dans les cas (button*, checkbox*, radiobutton*, tabpane*, textfield*, panel*), je me demande si tu veux pas (button | checkbox | radiobutton | tabpane | textfield | panel)* plutôt.

[codebox]<?xml version="1.0" encoding="UTF-8"?>

[/codebox]

Et la version XSD, générée à partir de la DTD :
[codebox]<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs=“http://www.w3.org/2001/XMLSchema” elementFormDefault=“qualified”>
<xs:element name=“screenonthefly”>
xs:complexType
xs:sequence
<xs:element minOccurs=“0” maxOccurs=“unbounded” ref=“panel”/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name=“panel”>
xs:complexType
xs:sequence
<xs:element minOccurs=“0” maxOccurs=“unbounded” ref=“button”/>
<xs:element minOccurs=“0” maxOccurs=“unbounded” ref=“checkbox”/>
<xs:element minOccurs=“0” maxOccurs=“unbounded” ref=“radiobutton”/>
<xs:element minOccurs=“0” maxOccurs=“unbounded” ref=“tabpane”/>
<xs:element minOccurs=“0” maxOccurs=“unbounded” ref=“textfield”/>
<xs:element minOccurs=“0” maxOccurs=“unbounded” ref=“panel”/>
</xs:sequence>
<xs:attribute name=“layout” use=“required”>
xs:simpleType
<xs:restriction base=“xs:token”>
<xs:enumeration value=“FormLayout”/>
<xs:enumeration value=“FlowLayout”/>
<xs:enumeration value=“BorderLayout”/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name=“columns”/>
<xs:attribute name=“rows”/>
<xs:attribute name=“align”/>
<xs:attribute name=“contraints”/>
</xs:complexType>
</xs:element>
<xs:element name=“tabpane”>
xs:complexType
xs:sequence
<xs:element minOccurs=“0” maxOccurs=“unbounded” ref=“pane”/>
</xs:sequence>
<xs:attribute name=“contraints” use=“required”/>
</xs:complexType>
</xs:element>
<xs:element name=“pane”>
xs:complexType
xs:sequence
<xs:element minOccurs=“0” maxOccurs=“unbounded” ref=“button”/>
<xs:element minOccurs=“0” maxOccurs=“unbounded” ref=“checkbox”/>
<xs:element minOccurs=“0” maxOccurs=“unbounded” ref=“radiobutton”/>
<xs:element minOccurs=“0” maxOccurs=“unbounded” ref=“tabpane”/>
<xs:element minOccurs=“0” maxOccurs=“unbounded” ref=“textfield”/>
<xs:element minOccurs=“0” maxOccurs=“unbounded” ref=“panel”/>
</xs:sequence>
<xs:attribute name=“title” use=“required”/>
</xs:complexType>
</xs:element>
<xs:element name=“label”>
xs:complexType
<xs:attribute name=“contraints” use=“required”/>
<xs:attribute name=“title” use=“required”/>
</xs:complexType>
</xs:element>
<xs:element name=“button”>
xs:complexType
<xs:attribute name=“contraints” use=“required”/>
<xs:attribute name=“action” use=“required”/>
</xs:complexType>
</xs:element>
<xs:element name=“checkbox”>
xs:complexType
<xs:attribute name=“contraints” use=“required”/>
<xs:attribute name=“property” use=“required”/>
</xs:complexType>
</xs:element>
<xs:element name=“radiobutton”>
xs:complexType
<xs:attribute name=“contraints” use=“required”/>
<xs:attribute name=“property” use=“required”/>
<xs:attribute name=“value” use=“required”/>
</xs:complexType>
</xs:element>
<xs:element name=“textfield”>
xs:complexType
<xs:attribute name=“contraints” use=“required”/>
<xs:attribute name=“property” use=“required”/>
</xs:complexType>
</xs:element>
</xs:schema>
[/codebox]