Hi,
es gibt heutzutage in Java verschiedene Libraries, die
- aus dem XML-Schema,
- einer mapping Datei,
- einem Java-Bean
- einem einkommenden xml file
prima mit sehr wenig Code xml Dateien in Java Objekt Strukturen umwandeln können.
(JAXB oder http://xmlbeans.apache.org/ ).
Ich habe leider noch keine praktische Erfahrung damit. Und die Schemastruktur der täglichen Wechselkurse der EZB sieht ein bischen merkwürdig aus, um damit unter dem normalen Zeitdruck jetzt anzufangen.
<?xml version="1.0" encoding="UTF-8"?>
<gesmes:Envelope xmlns:gesmes="http://www.gesmes.org/xml/2002-08-01" xmlns="http://www.ecb.int/vocabulary/2002-08-01/eurofxref">
<gesmes:subject>Reference rates</gesmes:subject>
<gesmes:Sender>
<gesmes:name>European Central Bank</gesmes:name>
</gesmes:Sender>
<Cube>
<Cube time='2006-02-13'>
<Cube currency='USD' rate='1.1888'/>
<Cube currency='JPY' rate='140.35'/>
[...stark gekürzt... Axel]
</Cube>
</Cube>
</gesmes:Envelope>
Man kann da natürlich immer mit der DOM-Api ran. Aber das ist vermutlich unnötig und es erzeugt ziemlich chaotischen Code:
Der ist übrigens ziemlich "notes-ähnlich", womit ich nicht sagen will, dass Notes chaotisch ist, sondern einfach, dass xml als Datenbank ziemlich notes-ähnlich ist.
(ich zerleg den Code natürlich noch in mehrere private functions).
InputStream is = null;
try {
if (get.getStatusCode() != 200) {
errMsg = "Die URL ist nicht erreichbar:" + urlEcbDaily
+ ". (http-Statuscode=" + get.getStatusCode();
throw new WebRetrievalException(errMsg);
}
is = get.getResponseBodyAsStream();
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
// erzeuge Dokument
Document doc = db.parse(is);
// hole alle Nodes mit dem Namen Cube (wie notesDocumentCollection.getAllDocumentsByKey()
NodeList nlCube = doc.getElementsByTagName("Cube");
Date date = null;
ExchangeRate exchRate = null;
// hier kommen die JavaBeans rein
Set exchRates = new HashSet();
for (int i = 0; i < nlCube.getLength(); i++) {
// iteriere über alle Elemente Cube.
Element cubeElement = (Element) nlCube.item(i);
if (cubeElement.getNodeType() == cubeElement.ELEMENT_NODE) {
// hole alle Attribute der node und iteriere über sie.
// im Element <Cube currency='MYR' rate='4.4265'/> sind currency="MYR" und rate="4.4265" die Attribute.
NamedNodeMap cubeAttr = cubeElement.getAttributes();
for (int j = 0; j < cubeAttr.getLength(); j++) {
Node attr = cubeAttr.item(j);
String attrName = attr.getNodeName();
// je nach dem Namen des Attributs mache unterschiedliche Operationen
// (Beans erzeugen, in einen Set (-> sowas wie ein dynamischer Array) tun, etc.
if (attrName.equals("time")) {
String[] dateParts = attr.getNodeValue().split("-");
date = new Date();
date.setYear(Integer.parseInt(dateParts[0]));
date.setMonth(Integer.parseInt(dateParts[1]) - 1);
date.setDate(Integer.parseInt(dateParts[2]));
date.setHours(0);
date.setMinutes(0);
date.setSeconds(0);
System.out.println("date=" + date);
} else if ((attrName.equals("currency"))
|| (attrName.equals("rate"))) {
if (j == 0) {
exchRate = new ExchangeRate();
exchRates.add(exchRate);
exchRate.setDate(date);
}
if (attrName.equals("currency")) {
exchRate.setCurrencyCode(attr.getNodeValue());
}
else if (attrName.equals("rate")) {
exchRate.setRate(Double.parseDouble(attr
.getNodeValue()));
}
System.out.println(" Attribute: (" + j + ")"
+ attr.getNodeName() + " = "
+ attr.getNodeValue());
}
}
}
}
System.out.println(exchRates);
}
Zur Not geht also die DOM-APi und sie ist ziemlich notes-ähnlich, wie gesagt.
Weiss jemand irgendwelche bessere Ideen.
Und die Struktur des xml files scheint mir echt nicht so richtig koscher zu sein.
Es gibt 2 Namespaces. Und die Cube Elemente sind so merkwürdig geschachtelt.
Keine direkte Frage, aber kann jemand etwas intelligentes posten?
Gruß Axel
dom4j mit xpath sieht gut aus. Werd das morgen direkt mal machen:
Kapitel using xPath:
XPath xpathSelector = DocumentHelper.createXPath("//Cube/Cube[@time]");
List results = xpathSelector.selectNodes(doc);
-> alle Notes mit datum
XPath xpathSelector = DocumentHelper.createXPath("//Cube/Cube[@currency]");
List results = xpathSelector.selectNodes(doc);
Wie mache ich einen xslt-node Selektor, für Elemente, die currency UND rate haben?
//Cube/Cube[@currency and @rate]
kanns jetzt nicht ausprobieren, wäre aber gut.