Afficher des informations sur un fichier XML
XML Parser
Dans cet exercice, on va parcourir un fichier XML et puis afficher dans la console les différentes informations présentes dans ce fichier.
L'affichage dans la console doit ressembler à l'exemple ci-dessous.
Debut de l'analyse du document
Ouverture de la balise : [Nom de la balise]
--------- Traitement du namespace : [URI du Namespace] dont le prefix est : [Prefix] --------
Ouverture de la balise : [Nom de la balise ]
appartenant au namespace : [URI du namespace]
Attributs :
- Attribut [Clée de l'attribut] = [Valeur de l'attribut ]
--------------------- Fin de traitement du namespace : [Prefix] ------------------
Fermeture de la balise : [Nom de la balise]
Fin de l'analyse du document
Debut de l'analyse du document Ouverture de la balise : [Nom de la balise] --------- Traitement du namespace : [URI du Namespace] dont le prefix est : [Prefix] -------- Ouverture de la balise : [Nom de la balise ] appartenant au namespace : [URI du namespace] Attributs : - Attribut [Clée de l'attribut] = [Valeur de l'attribut ] --------------------- Fin de traitement du namespace : [Prefix] ------------------ Fermeture de la balise : [Nom de la balise] Fin de l'analyse du document
Question
Téléchargez cette archive contenant une version incomplète de la solution, puis ouvrez la avec Eclipse.
Vous trouverez les fichiers nécessaires dans le dossier Ressource.
Question
Remplissez les interfaces nécessaires pour avoir l'affichage souhaité dans la console.
Pour les attributs, utilisez les méthodes getLocalName() et getValue() de l'instance attributs.
Pour la gestion des namespace, vous pouvez utiliser la feature qui est dédié pour cela.
reader.setFeature("http://xml.org/sax/features/namespaces", true);
reader.setFeature("http://xml.org/sax/features/namespace-prefixes",true);
reader.setFeature("http://xml.org/sax/features/namespaces", true); reader.setFeature("http://xml.org/sax/features/namespace-prefixes",true);
Il faut aussi implémenter l'interface ErrorHandler pour afficher toutes les types d'erreur possible.
ContentHandler
public class myContentHandler implements ContentHandler {
private Locator locator;
public myContentHandler()
{
super();
locator = new LocatorImpl();
}
/**
* Definir le locator.
*/
@Override
public void setDocumentLocator(Locator value) {
locator= value;
}
/**
* Evenement recu au debut de l'analyse du document XML
*/
@Override
public void startDocument() throws SAXException {
System.out.println("Debut de l'analyse du document");
}
/**
* Evenement recu a la fin de l'analyse du document XML
*/
@Override
public void endDocument() throws SAXException {
System.out.println("Fin de l'analyse du document" );
}
/**
* Evenement recu au debut du mapping sur un namespace
* @param prefix le nom du préfixe choisi.
* @param URI le lien du namespace
*/
@Override
public void startPrefixMapping(String prefix, String URI) throws SAXException {
System.out.print("----------------------------- ");
System.out.print("Traitement du namespace : " + URI + " dont le prefix est : " + prefix);
System.out.println(" -----------------------------");
}
/**
* Evenement recu a la fin du mapping sur un namespace
* @param prefix le nom du préfixe choisi.
*/
@Override
public void endPrefixMapping(String prefix) throws SAXException {
System.out.print("--------------------- ");
System.out.print("Fin de traitement du namespace : " + prefix);
System.out.println(" ------------------");
}
/**
* Evenement recu a chaque fois que l'analyseur rencontre une balise XML ouvrante.
* @param nameSpaceURI l'URL de l'espace de nommage.
* @param localName le nom local de la balise.
* @param rawName nom de la balise en version 1.0 <code>nameSpaceURI + ":" + localName</code>
*/
@Override
public void startElement(String nameSpaceURI, String localName, String rawName, Attributes attributs) throws SAXException {
System.out.println("Ouverture de la balise : " + localName);
if ( ! "".equals(nameSpaceURI)) {
System.out.println(" appartenant au namespace : " + nameSpaceURI);
}
if(attributs.getLength()!=0)
System.out.println(" Attributs : ");
for (int index = 0; index < attributs.getLength(); index++) {
System.out.println(" - Attribut "+ (index+1) + attributs.getLocalName(index) + " = " + attributs.getValue(index));
}
}
/**
* Evenement recu a chaque fois que l'analyseur rencontre une balise XML ouvrante.
* @param nameSpaceURI l'URL de l'espace de nommage.
* @param localName le nom local de la balise.
* @param rawName nom de la balise en version 1.0 <code>nameSpaceURI + ":" + localName</code>
*/
@Override
public void endElement(String nameSpaceURI, String localName, String rawName) throws SAXException {
System.out.print("Fermeture de la balise : " + localName);
if ( ! "".equals(nameSpaceURI)) { // name space non null
System.out.print(" appartenant a l'espace de nommage : " + localName);
}
System.out.println();
}
/**
* @param ch les caracteres qui sont dans un élément.
* @param start le rang du premier caractere a traiter .
* @param length la taille de la chaine a traiter.
*/
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
System.out.println("Texte : " + new String(ch, start, length));
}
@Override
public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException {
System.out.println("Espace inutile : " + new String(ch, start, length));
}
@Override
public void processingInstruction(String target, String data) throws SAXException {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public void skippedEntity(String string) throws SAXException {
throw new UnsupportedOperationException("Not supported yet.");
}
}
public class myContentHandler implements ContentHandler { private Locator locator; public myContentHandler() { super(); locator = new LocatorImpl(); } /** * Definir le locator. */ @Override public void setDocumentLocator(Locator value) { locator= value; } /** * Evenement recu au debut de l'analyse du document XML */ @Override public void startDocument() throws SAXException { System.out.println("Debut de l'analyse du document"); } /** * Evenement recu a la fin de l'analyse du document XML */ @Override public void endDocument() throws SAXException { System.out.println("Fin de l'analyse du document" ); } /** * Evenement recu au debut du mapping sur un namespace * @param prefix le nom du préfixe choisi. * @param URI le lien du namespace */ @Override public void startPrefixMapping(String prefix, String URI) throws SAXException { System.out.print("----------------------------- "); System.out.print("Traitement du namespace : " + URI + " dont le prefix est : " + prefix); System.out.println(" -----------------------------"); } /** * Evenement recu a la fin du mapping sur un namespace * @param prefix le nom du préfixe choisi. */ @Override public void endPrefixMapping(String prefix) throws SAXException { System.out.print("--------------------- "); System.out.print("Fin de traitement du namespace : " + prefix); System.out.println(" ------------------"); } /** * Evenement recu a chaque fois que l'analyseur rencontre une balise XML ouvrante. * @param nameSpaceURI l'URL de l'espace de nommage. * @param localName le nom local de la balise. * @param rawName nom de la balise en version 1.0 <code>nameSpaceURI + ":" + localName</code> */ @Override public void startElement(String nameSpaceURI, String localName, String rawName, Attributes attributs) throws SAXException { System.out.println("Ouverture de la balise : " + localName); if ( ! "".equals(nameSpaceURI)) { System.out.println(" appartenant au namespace : " + nameSpaceURI); } if(attributs.getLength()!=0) System.out.println(" Attributs : "); for (int index = 0; index < attributs.getLength(); index++) { System.out.println(" - Attribut "+ (index+1) + attributs.getLocalName(index) + " = " + attributs.getValue(index)); } } /** * Evenement recu a chaque fois que l'analyseur rencontre une balise XML ouvrante. * @param nameSpaceURI l'URL de l'espace de nommage. * @param localName le nom local de la balise. * @param rawName nom de la balise en version 1.0 <code>nameSpaceURI + ":" + localName</code> */ @Override public void endElement(String nameSpaceURI, String localName, String rawName) throws SAXException { System.out.print("Fermeture de la balise : " + localName); if ( ! "".equals(nameSpaceURI)) { // name space non null System.out.print(" appartenant a l'espace de nommage : " + localName); } System.out.println(); } /** * @param ch les caracteres qui sont dans un élément. * @param start le rang du premier caractere a traiter . * @param length la taille de la chaine a traiter. */ @Override public void characters(char[] ch, int start, int length) throws SAXException { System.out.println("Texte : " + new String(ch, start, length)); } @Override public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException { System.out.println("Espace inutile : " + new String(ch, start, length)); } @Override public void processingInstruction(String target, String data) throws SAXException { throw new UnsupportedOperationException("Not supported yet."); } @Override public void skippedEntity(String string) throws SAXException { throw new UnsupportedOperationException("Not supported yet."); } }
Complément : ErrorHandler
public class myErrorHandler implements ErrorHandler{
@Override
public void warning(SAXParseException SaxException) throws SAXException {
System.out.println("Warning : "+SaxException.getMessage());
}
@Override
public void error(SAXParseException SaxException) throws SAXException {
System.out.println("Non fatal error : "+SaxException.getMessage());
}
@Override
public void fatalError(SAXParseException SaxException) throws SAXException {
System.out.println("Fatal error : "+SaxException.getMessage());
}
}
public class myErrorHandler implements ErrorHandler{ @Override public void warning(SAXParseException SaxException) throws SAXException { System.out.println("Warning : "+SaxException.getMessage()); } @Override public void error(SAXParseException SaxException) throws SAXException { System.out.println("Non fatal error : "+SaxException.getMessage()); } @Override public void fatalError(SAXParseException SaxException) throws SAXException { System.out.println("Fatal error : "+SaxException.getMessage()); } }
Complément : mySAXReader
public mySAXReader(String uri) throws SAXException, IOException, ParserConfigurationException
{
XMLReader reader = XMLReaderFactory.createXMLReader("org.apache.xerces.parsers.SAXParser");
reader.setFeature("http://xml.org/sax/features/validation", true);
reader.setFeature("http://xml.org/sax/features/namespaces", true);
reader.setFeature("http://xml.org/sax/features/namespace-prefixes",true);
reader.setContentHandler(new myContentHandler());
reader.setErrorHandler(new myErrorHandler());
reader.parse(new InputSource(uri));
}
public mySAXReader(String uri) throws SAXException, IOException, ParserConfigurationException { XMLReader reader = XMLReaderFactory.createXMLReader("org.apache.xerces.parsers.SAXParser"); reader.setFeature("http://xml.org/sax/features/validation", true); reader.setFeature("http://xml.org/sax/features/namespaces", true); reader.setFeature("http://xml.org/sax/features/namespace-prefixes",true); reader.setContentHandler(new myContentHandler()); reader.setErrorHandler(new myErrorHandler()); reader.parse(new InputSource(uri)); }
Question
Dans cette question, vous serez invitées à garder vos Handler déjà faits pour la question précédente.
On va analyser de la même façon un autre fichier XML. Pour cela, vous allez ouvrir le fichier file2.xml dans votre fonction main.
L'analyse se traite bien ? Si non, expliquez pourquoi et trouvez une solution sans modifié le fichier file2.xml.
Utilisez les EntityResolver pour changer la DTD utilisé.
Fondamental : Explication
Le problème provient du fichier DTD qui est référencé dans le XML. En effet, le XML rajoute une balise qui n'est pas déclarée dans la DTD.
Pour résoudre ce problème, on peut utiliser un autre fichier DTD qui est plus conforme avec le XML. Pour cela on doit utiliser l'interface EntityResolver.
Le code source à introduire :
Dans la classe mySAXReader :
reader.setFeature("http://xml.org/sax/features/validation", true);
reader.setEntityResolver(new myEntityResolver());
reader.setFeature("http://xml.org/sax/features/validation", true); reader.setEntityResolver(new myEntityResolver());
Dans la classe myEntityResolver
@Override
public InputSource resolveEntity(String publicID, String systemID) throws SAXException, IOException {
System.out.println("Resolve entity : public ID : "+publicID+" SystemID : "+systemID);
return new InputSource("fileCorrect.dtd");
}
@Override public InputSource resolveEntity(String publicID, String systemID) throws SAXException, IOException { System.out.println("Resolve entity : public ID : "+publicID+" SystemID : "+systemID); return new InputSource("fileCorrect.dtd"); }
Complément :
Cela reste un cas très simple et basique.
Souvent cette classe est utile quand on a des références avec des PublicID, et qu'on souhaite au lieu de ça utiliser des ressources local avec SystemID.
Exemple : on référence un schéma qui est publié sur internet, mais on n'a pas accès à internet, donc on souhaite utilisez un schéma local. Dans ce cas on appelle la classe EntityResolver qui envoie le bon fichier à utiliser.
La solution complète :
Téléchargez cette archive contenant une version complète de la solution