2016-11-22 7 views
1

Ich versuche, diese XML zu analysieren:Wie analysiert man dieses bereitgestellte XML mit java.xml.xpath?

<?xml version="1.0" encoding="UTF-8"?> 
<veranstaltungen> 
    <veranstaltung id="201611211500#25045271"> 
    <titel>Mal- und Zeichen-Treff</titel> 
    <start>2016-11-21 15:00:00</start> 
    <veranstaltungsort id="20011507"> 
     <name>Freizeitclub - ganz unbehindert </name> 
     <anschrift>Macht los e.V. 
Lipezker Straße 48 
03048 Cottbus 
</anschrift> 
     <telefon>xxxx xxxx </telefon> 
     <fax>0355 xxxx</fax> 
[...] 
</veranstaltungen> 

Wie Sie, einige der Texte haben Leerzeichen oder sogar Zeilenumbrüche sehen. Ich habe Probleme mit dem Text vom Knoten anschrift, weil ich die richtigen Standortdaten in einer Datenbank finden muss. Das Problem ist, das zurückgegebene String ist:

Macht los e.V.Lipezker Straße 4803048 Cottbus 

statt:

Macht los e.V. Lipezker Straße 48 03048 Cottbus 

Ich kenne den richtigen Weg, um es mit normalie-space() sein analysieren soll, aber ich kann nicht ganz herausfinden, wie es zu tun. Ich versuchte dies:

// Does not work; afaik because xpath 1 normalizes just the first node 
xPath.compile("normalize-space(veranstaltungen/veranstaltung[position()=1]/veranstaltungsort/anschrift/text()")); 

// Does not work 
xPath.compile("veranstaltungen/veranstaltung[position()=1]/veranstaltungsort[normalize-space(anschrift/text())]")); 

Ich versuchte auch hier die Lösung gegeben: xpath-normalize-space-to-return-a-sequence-of-normalized-strings

xPathExpression = xPath.compile("veranstaltungen/veranstaltung[position()=1]/veranstaltungsort"); 
NodeList result = (NodeList) xPathExpression.evaluate(doc, XPathConstants.NODESET); 

String normalize = "normalize-space(.)"; 
xPathExpression = xPath.compile(normalize); 

int length = result.getLength(); 
for (int i = 0; i < length; i++) { 
    System.out.println(xPathExpression.evaluate(result.item(i), XPathConstants.STRING)); 
} 

System.out druckt:

Macht los e.V.Lipezker Straße 4803048 Cottbus 

Was mache ich falsch?

aktualisieren

Ich habe eine Abhilfe schon, aber das kann die Lösung nicht sein. Die folgenden Zeilen zeigen, wie ich den String zusammen aus der Httpresponse:

try (BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), Charset.forName(charset)))) { 
    final StringBuilder stringBuilder = new StringBuilder(); 
    String    line; 

    while ((line = reader.readLine()) != null) { 
    // stringBuilder.append(line); 
    // WORKAROUND: Add a space after each line 
    stringBuilder.append(line).append(" "); 
    } 

    // Work with the red lines 
} 

ich eher eine feste Lösung haben würde.

+0

'normalize-space()' Streifen führende und nachfolgende Leerzeichen und wandelt andere Sequenzen von Leerzeichen (einschließlich Zeilenumbrüche) in ein einzelnes Leerzeichen. Da Ihr Ergebnis zwischen den Zeilen des Textinhalts des Anschriftzeichens keinen Abstand hat, muss etwas Ihre Zeilenumbrüche * essen, bevor * normalize-space() 'seine Aufgabe erfüllen kann. – Markus

Antwort

1

Ursprünglich scheinen Sie zum Lesen des XML mit dem folgenden Code zu:

try (BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), Charset.forName(charset)))) { 
    final StringBuilder stringBuilder = new StringBuilder(); 
    String    line; 

    while ((line = reader.readLine()) != null) { 
    stringBuilder.append(line); 
    } 

} 

Hier wird Ihre neue Zeilen gefressen: readline() tun nicht Rückkehr der hinteren Zeilenumbrüche. Wenn Sie dann den Inhalt des Objekts stringBuilder analysieren, erhalten Sie ein falsches DOM, wobei die Textknoten die ursprünglichen Zeilenumbrüche aus dem XML nicht enthalten.

+0

Ich wusste das nicht. Danke für die Info. Meine Lösung ist dann zu überprüfen, ob die Zeile mit einem '>' endet und wenn kein ' ' hinzugefügt wird. – aProgger

+2

Tun Sie das nicht. Sie ändern die Eingabe erneut. Warum möchten Sie zeilenbasiertes Lesen durchführen? Warum analysieren Sie den Eingabestream nicht so wie er ist? – Markus

+0

Ich sollte meinen Kopf für eine Weile klar machen. Du hast recht. Werde das jetzt tun. – aProgger

0

Dank der Hilfe von Markus konnte ich das Problem lösen. Der Grund war die readLine() - Methode des BufferedReader, die Zeilenumbrüche verwarf. Die folgende CodeSnippet funktioniert für mich (Vielleicht kann sie verbessert werden):

public Document getDocument() throws IOException, ParserConfigurationException, SAXException { 

    final HttpResponse response = getResponse(); // returns a HttpResonse 
    final HttpEntity entity = response.getEntity(); 
    final Charset  charset = ContentType.getOrDefault(entity).getCharset(); 

    // Not 100% sure if I have to close the InputStreamReader. But I guess so. 
    try (InputStreamReader isr = new InputStreamReader(entity.getContent(), charset == null ? Charset.forName("UTF-8") : charset)) { 
    return documentBuilderFactory.newDocumentBuilder().parse(new InputSource(isr)); 
    } 
} 
Verwandte Themen