Lecture Multi-Niveau des fichiers XML en Java
Jusqu'à récemment, le tag de la structure de mes fichiers XML sont assez simples. Mais maintenant, j'ai un niveau supplémentaire de tags avec des balises, et de l'analyse du XML est devenu plus compliqué.
Voici un exemple de mes nouveaux fichiers XML (j'ai changé les noms de balise pour le rendre plus facile à comprendre):
<SchoolRoster>
<Student>
<name>John</name>
<age>14</age>
<course>
<math>A</math>
<english>B</english>
</course>
<course>
<government>A+</government>
</course>
</Student>
<Student>
<name>Tom</name>
<age>13</age>
<course>
<gym>A</gym>
<geography>incomplete</geography>
</course>
</Student>
</SchoolRoster>
Les caractéristiques importantes de l'XML ci-dessus, c'est que je peut avoir plusieurs "cours" des attributs, et à l'intérieur que je peux avoir nommé arbitrairement les balises de leurs enfants. Et il peut y avoir un certain nombre de ces enfants, à qui je veux lire dans une table de hachage de "nom", "valeur".
public static TreeMap getAllSchoolRosterInformation(String fileName) {
TreeMap SchoolRoster = new TreeMap();
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
File file = new File(fileName);
if (file.exists()) {
Document doc = db.parse(file);
Element docEle = doc.getDocumentElement();
NodeList studentList = docEle.getElementsByTagName("Student");
if (studentList != null && studentList.getLength() > 0) {
for (int i = 0; i < studentList.getLength(); i++) {
Student aStudent = new Student();
Node node = studentList.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
Element e = (Element) node;
NodeList nodeList = e.getElementsByTagName("name");
aStudent.setName(nodeList.item(0).getChildNodes().item(0).getNodeValue());
nodeList = e.getElementsByTagName("age");
aStudent.setAge(Integer.parseInt(nodeList.item(0).getChildNodes().item(0).getNodeValue()));
nodeList = e.getElementsByTagName("course");
if (nodeList != null && nodeList.getLength() > 0) {
Course[] courses = new Course[nodeList.getLength()];
for (int j = 0; j < nodeList.getLength(); j++) {
Course singleCourse = new Course();
HashMap classGrades = new HashMap();
NodeList CourseNodeList = nodeList.item(j).getChildNodes();
for (int k = 0; k < CourseNodeList.getLength(); k++) {
if (CourseNodeList.item(k).getNodeType() == Node.ELEMENT_NODE && CourseNodeList != null) {
classGrades.put(CourseNodeList.item(k).getNodeName(), CourseNodeList.item(k).getNodeValue());
}
}
singleCourse.setRewards(classGrades);
Courses[j] = singleCourse;
}
aStudent.setCourses(Courses);
}
}
SchoolRoster.put(aStudent.getName(), aStudent);
}
}
} else {
System.exit(1);
}
} catch (Exception e) {
System.out.println(e);
}
return SchoolRoster;
}
Le problème, je suis en cours d'exécution en est qu'au lieu d'obtenir que l'étudiant a obtenu Un "a" dans "math", ils obtiennent une valeur null dans les "mathématiques". (Si ce post est trop long, je peux essayer de trouver un moyen de le raccourcir.)
Ouais, ça avait l'air drôle pour moi. Si c'était mon projet, j'aurais une liste de Cours et de l'utilisation
<course>
comme une balise avec <courseName>
et <grade>
comme un subtags.C'est précis. J'ai seulement besoin d'un grade 'A' pour les Mathématiques. Mais je pourrais avoir une longue liste de <course></> options, qui peuvent chacune avoir plusieurs classes comme les "Mathématiques".
il peut être "précis", mais ce n'est pas la bonne forme.
JAXB (JSR-222) est en fait une série avec plusieurs implémentations open source: Métro, MOXy (je suis le tech lead), etc. Une mise en œuvre est inclus dans le JDK et c'est la norme de Service de liaison de la couche de JAX-WS et JAX-RS. Voici une comparaison avec XStream: blog.bdoughan.com/2010/10/how-does-jaxb-compare-to-xstream.html
OriginalL'auteur theJollySin | 2012-06-29
Vous devez vous connecter pour publier un commentaire.
Vous appelez
getNodeValue()
sur unElement
. Selon le JDK API docs, qui renvoie la valeur null.http://docs.oracle.com/javase/6/docs/api/org/w3c/dom/Node.html
Vous avez besoin pour obtenir l'enfant du nœud de Texte et appel
getNodeValue()
. Voici une très rapide et sale façon de le faire:S'il vous plaît ne pas l'utiliser dans le code de production. C'est laid. Mais il va vous diriger dans la bonne direction.
ma solution proposée est laid peu, pas votre code 🙂 je ne suis pas correctement, vérifier la valeur de retour de
getChildNodes()
ouitem(0)
et je ne suis pas vérifier quegetChildNodes().item(0)
est de type TEXT_NODE avant d'appelergetNodeValue()
sur elle. L'extrait de code que je vous ai donné fonctionne très bien maintenant, mais je voudrais ajouter dans certaines vérifications avant de l'utiliser dans un environnement réel.OriginalL'auteur Dan O
Si c'était mon projet, je voudrais éviter d'essayer manuellement disséquer les données dans le format HTML et au lieu de laisser Java le faire pour moi en utilisant JAXB. La plus-je utiliser cet outil, plus je l'aime. Je vous invite à envisager d'essayer cela, car si vous le faites, tout ce que vous avez besoin de changer le code XML en objets Java est bon annotations dans vos classes Java et puis unmarshall le XML. Le code utilisé sera beaucoup plus simple et nettement moins susceptibles d'avoir des erreurs.
Par exemple, le code suivant mobilisé les informations dans un fichier XML assez facilement et proprement:
Ce qui a entraîné dans le code XML suivant:
À unmarshall ce dans un SchoolRoster de classe rempli avec des données ne prendra que quelques lignes de code.
Après l'ajout de
toString()
méthodes pour mes classes, ce qui a entraîné l':veuillez voir modifier.
OriginalL'auteur Hovercraft Full Of Eels
Comme @Aéroglisseur je recommande d'utiliser une bibliothèque pour les poignées de la sérialisation xml. J'ai trouvé Xstream pour la grande performance et facile à utiliser.
http://x-stream.github.io/
Par exemple:
XML exemple pour démontrer une propriété nested:
OriginalL'auteur Thorn