[Java]HttpClient: hoe XML strippen?

Pagina: 1
Acties:

  • Deathchant
  • Registratie: September 2003
  • Laatst online: 22-05 16:51

Deathchant

Don't intend. Do!

Topicstarter
Hallo mensen, kep een beetje rondgesnuffeld, maar kep alleen info gevonden over het inlezen van XML naar Document Object Modellen.

Ik krijg van een externe Servlet een HttpResponse terug (HTML en XML).

zie de code

code:
1
2
3
GetMethod get = new GetMethod(eenURI);
int status = httpClient.executeMethod(get);
byte[] b = get.getResponseBody();


ik zet die HttpResponse dus in een byte array.

Nou heb ik in de classe ResponseStripper een method "strip()".
Deze method moet de HttpResponse op deze manier strippen:

Zo ziet het eruit:
code:
1
2
3
4
5
6
7
8
9
10
11
<HTML>
...
...
<response-message>
   <message-ack>acknowlegde</message-ack>
   <item>76</item>
   ...
   ...
</response-message>

</HTML>


Ik wil dus dat deze response op dusdanige manier gestript wordt dat alleen vanaf de <response-message>....</response-message> over blijft.
Dus na strippen moet ik alleen dit overhebben:
code:
1
2
3
4
5
6
<response-message>
   <message-ack>acknowlegde</message-ack>
   <item>76</item>
   ...
   ...
</response-message>


Dit moet vervolgens weer in een byte[] teruggezet worden en geretourneerd worden aan de HttpClient.
De reden dat ik nu post is omdat ik snel klaar moet zijn met dit. Ik zal zelf uiteraard ook nog zelf proberen hoor (voor het geval hier commentaar op wordt gegeven).

Misschien dat iemand al wat voorzetjes kan geven.

Canon: EOS R6 | EF 16-35/4L IS USM | EF 70-200/2.8L IS II USM
Zeiss: 35/2 Distagon | 50/2 Makro-Planar | 85/1.4 Planar | 100/2 Makro-Planar | 135/2 Apo Sonnar


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

Je kan toch je chararray afscannen op:
<response-message> en </response-message>

  • pgussow
  • Registratie: Maart 2003
  • Laatst online: 18-08-2025
En als binnen de response tag toevallig die tag nog een keer voorkomt?

Ik zou kijken of ik het hele document (Dus inclusief de HTML) in een DOM implementatie zou kunnen lezen en vervolgens via XPath je eigenlijke root eruit halen. Lijkt me wat flexibeler...

  • Deathchant
  • Registratie: September 2003
  • Laatst online: 22-05 16:51

Deathchant

Don't intend. Do!

Topicstarter
nee, de persoon die deze output genereert zorgt ervoor dat die maar 1 keer voorkomt. Dus hier kan ik vanuit gaan.

Dus jij zegt dat ik met documentbuilder en documentbuilderfactory etc. aan de slag moet? met nodelists enzo

Ik weet namelijk ff snel niet zo hoe ik dit moet doen. Ik moet dan ook nog de gestripte versie weer als byte[] terug geven (of als DOM dat weet ik nog niet)

Canon: EOS R6 | EF 16-35/4L IS USM | EF 70-200/2.8L IS II USM
Zeiss: 35/2 Distagon | 50/2 Makro-Planar | 85/1.4 Planar | 100/2 Makro-Planar | 135/2 Apo Sonnar


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

pgussow schreef op 21 juli 2004 @ 08:47:
En als binnen de response tag toevallig die tag nog een keer voorkomt?
Daar kan je je statemachine natuurlijk op afstemmen.

  • Deathchant
  • Registratie: September 2003
  • Laatst online: 22-05 16:51

Deathchant

Don't intend. Do!

Topicstarter
als ik nou zeg dat ik een syntax correcte HTML/XML in die reponse geleverd krijg....dan kan ik gewoon idd die XML parsen, toch?

Dan kan ik die als inputstream doorkrijgen en dan in een DOM gooien. Kijk hieronder:
code:
1
2
3
4
5
6
7
8
9
10
private DocumentBuilderFactory dbf;
private DocumentBuilder builder;
private Document doc;
GetMehod get = new HttpMethod();
...
...
...
...
httpClient.executeMethod(get);
doc = builder.parse(get.getResponseBodyAsStream);
doc geeft dan de precieze XML structuur weer toch?

Moet ik dan nu in de strip() method met de NodeList en Nodes zoeken naar die <response-message>? misschien dat iemand me dat ff kan vertellen

[ Voor 13% gewijzigd door Deathchant op 21-07-2004 09:28 ]

Canon: EOS R6 | EF 16-35/4L IS USM | EF 70-200/2.8L IS II USM
Zeiss: 35/2 Distagon | 50/2 Makro-Planar | 85/1.4 Planar | 100/2 Makro-Planar | 135/2 Apo Sonnar


  • Deathchant
  • Registratie: September 2003
  • Laatst online: 22-05 16:51

Deathchant

Don't intend. Do!

Topicstarter
maar ik krijg net te horen dat dat niet lukt.

Het is de bedoeling dat ik die byte array afga naar de <response-message></response-message> tags.

ik moet deze tags, inclusief alle tussenliggende tags in een nieuwe byte[]
zetten.

Kan iemand me vertellen hoe ik die byte[] afga en alles filter wat ik nodig heb?

Canon: EOS R6 | EF 16-35/4L IS USM | EF 70-200/2.8L IS II USM
Zeiss: 35/2 Distagon | 50/2 Makro-Planar | 85/1.4 Planar | 100/2 Makro-Planar | 135/2 Apo Sonnar


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

Deathchant schreef op 21 juli 2004 @ 09:47:
ik moet deze tags, inclusief alle tussenliggende tags in een nieuwe byte[]
zetten.

Kan iemand me vertellen hoe ik die byte[] afga en alles filter wat ik nodig heb?
Dit is wel zwaar basic zeg. Je weet toch wel hoe je een array moet aflopen en controleren of er een reeks in zit die voldoet aan je wensen? Dit lijkt me echt zo`n probleem die je in je 1e week programmeerles krijgt.

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
XML zelf beetje gaan zitten scannen met handmatige code of reguliere expressies is *evil*.

Je moet een XML library gebruikt om de XML te verwerken. Je kan dit probleem heel eenvoudig oplossen met een DOM library, eventueel met eentje met XPath support. Als performance belangrijk is, zou je ook SAX kunnen gebruiken. Dit probleem is wel fraai te implementeren in SAX: je kan als je dit element binnenkomt tijdelijk overstappen op een ContentHandler die de XML gelijk weer wegschrijft.

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


  • Deathchant
  • Registratie: September 2003
  • Laatst online: 22-05 16:51

Deathchant

Don't intend. Do!

Topicstarter
ja ik weet het, ben een n00b :P

Maar ik kan nu gewoon zeggen getResponseBodyAsStream.

Kep nu de volgende code:
code:
1
2
3
InputStream is = get.getResponseBodyAsStream();
byte[] b = get.getResponseBody();
int length = b.length;
dan roep ik strip() aan:
code:
1
byte[] b2 = strip(is,length);

Dan in strip:
code:
1
2
3
4
5
6
7
8
9
10
11
public byte[] strip(InputStream is, int byteArrayLength) {
    int bytesRead = 0;  
    byte [] buffer = new byte[byteArrayLength];
    // lees het hele bytearray
    while ((bytesRead = is.read(buffer, 0, byteArrayLength) != -1) {
           // doe iets   
    }
    ....
    // returnwaarde moet van type byte[] zijn
    return byte[]
}


ik weet gewoon niet wat ik nu in die while moet zetten. In iedergeval moet ik <response-message>
<>
<>
</response-message>

eruit halen en wegschrijven naar een byte[].
Ik weet niet hoe dit moet. (ik moet zoeken naar de juiste tags en alles wat daarin staat ergens even wegschrijven. Dan moet ik het weggeschreven deel in byte[] zetten)

[ Voor 43% gewijzigd door Deathchant op 21-07-2004 10:55 ]

Canon: EOS R6 | EF 16-35/4L IS USM | EF 70-200/2.8L IS II USM
Zeiss: 35/2 Distagon | 50/2 Makro-Planar | 85/1.4 Planar | 100/2 Makro-Planar | 135/2 Apo Sonnar


  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
Kansloos: je moet XML niet op deze manier verwerken. Pak eens een willekeurige tutorial over XML processing: het web staat er vol mee.

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


  • Deathchant
  • Registratie: September 2003
  • Laatst online: 22-05 16:51

Deathchant

Don't intend. Do!

Topicstarter
Ik kan er niet vanuitgaan dat de XML correct aangeleverd wordt. Dus ik kan em niet parsen zodat het een DOM object wordt, want dan krijg je een foutmelding dat de syntax niet correct is of whatever voor fout. Dat is wel shit, want dan was het opgelost. Dan kon ik idd met de NodeList alle elementen uit de XML halen en wegschrijven naar een nieuw DOM object.
Ik MOET het resultaat in een byte[] wegschrijven.

Dit resultaat wordt vervolgens in een constructor mee gepleurd ter controle

Canon: EOS R6 | EF 16-35/4L IS USM | EF 70-200/2.8L IS II USM
Zeiss: 35/2 Distagon | 50/2 Makro-Planar | 85/1.4 Planar | 100/2 Makro-Planar | 135/2 Apo Sonnar


  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
Humz, dat zag ik nergens terug in in de vraag ... Welke gek levert er een mix van HTML (geen XHTML dus) en XML af? Ik zou het maar bij de bron aanpakken als ik jou was ;) .

[ Voor 5% gewijzigd door mbravenboer op 21-07-2004 11:00 ]

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


  • Deathchant
  • Registratie: September 2003
  • Laatst online: 22-05 16:51

Deathchant

Don't intend. Do!

Topicstarter
dat is het probleem net. Het gaat niet anders. Heb ik niks over te zeggen helaas :'(
ik moet nu gewoon even weten wat ik in die while lus moet doen.
Tis dat ik in feite een HTML uit de response krijg. In deze HTML zitten idd eigen gedefinieerde tags.

Ik moet zoeken naar 2 strings: <response-message> en </response-message>. Deze 2 en alles wat ertussen staat moet als byte[] worden teruggegeven.

De vraag is eigenlijk:
Ik heb deze code
while ((bytesRead = is.read(buffer, 0, byteArrayLength) != -1))

deze leest de hele inputstream. Ik kan toch niet een strings gaan zoeken in een inputstream ofwel ?

[ Voor 12% gewijzigd door Deathchant op 21-07-2004 11:13 ]

Canon: EOS R6 | EF 16-35/4L IS USM | EF 70-200/2.8L IS II USM
Zeiss: 35/2 Distagon | 50/2 Makro-Planar | 85/1.4 Planar | 100/2 Makro-Planar | 135/2 Apo Sonnar


Verwijderd

Je was op zoek naar het volgende??

Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import java.io.*;

public class LeesInOfzow {
    public byte[] strip(InputStream is) {  //Snap niet waarom je de lengte meegeeft (zal wel aan mij liggen)
    try {
        char[] START_TAG = new char[] { '<','r','e','s','p','o','n','s','e','-','m','e','s','s','a','g','e' };
        char[] EINDE_TAG = new char[] { '<', '/', 'r','e','s','p','o','n','s','e','-','m','e','s','s','a','g','e' }; 
        
        char[] buffer = new char[START_TAG.length];
        InputStreamReader reader = new InputStreamReader(is);
        int offset = 0, numRead=-1;
        StringBuffer returnBuffer = new StringBuffer();
        
        while( (numRead = reader.read(buffer,offset, buffer.length)) != -1) {
                offset += numRead;
                
                if(java.util.Arrays.equals(START_TAG, buffer)) {
                        returnBuffer.append(buffer);
                        buffer = new char[EINDE_TAG.length];
                        while( (numRead = reader.read(buffer, offset, buffer.length)) != -1) {
                                offset += numRead;
                                returnBuffer.append(buffer);
                                if(java.util.Arrays.equals(EINDE_TAG, buffer)
                                        return returnBuffer.toString().getBytes();
                        }   
                }
        }
    } catch(IOException ioe) {
        //Doe er iets mee?
    } finally {
        is.close();
    }
}


Ik heb de code niet gecompileerd maar hier zou je genoeg aanwijzingen uit moeten kunnen halen zo dacht ik :)
edit:
Klein bugje

[ Voor 16% gewijzigd door Verwijderd op 21-07-2004 12:08 ]


  • Deathchant
  • Registratie: September 2003
  • Laatst online: 22-05 16:51

Deathchant

Don't intend. Do!

Topicstarter
bedankt nochoice, ik zal het gaan uitproberen.
ik deed eerst die

byte[] b = get.getResponseBody (dat is een byte[])
dan int length = b.length
om zo de lengte van bytearray door te kunnen geven, zodat ik niet [8192] of iets dergelijks hoef te zeggen.

Kom er alleen niet echt uit waarom je een InputStreamReader kiest.

Edit: je hebt wel een mooie programmeerstijl vind ik. Mooi netjes, duidelijk. Alleen pleur ik overal commentaar bij en jij niet :P

[ Voor 18% gewijzigd door Deathchant op 21-07-2004 13:24 ]

Canon: EOS R6 | EF 16-35/4L IS USM | EF 70-200/2.8L IS II USM
Zeiss: 35/2 Distagon | 50/2 Makro-Planar | 85/1.4 Planar | 100/2 Makro-Planar | 135/2 Apo Sonnar


  • mulder
  • Registratie: Augustus 2001
  • Laatst online: 21:13

mulder

ik spuug op het trottoir

Maar zitten de HTML en de XML nu kompleet door elkaar, of is het een HTML met daar in een stuk XML?

oogjes open, snaveltjes dicht


  • Deathchant
  • Registratie: September 2003
  • Laatst online: 22-05 16:51

Deathchant

Don't intend. Do!

Topicstarter
dat laatste ;)

<html>
<head>
<response-message>
...
..
</response-message>
...
etc

ik ben nu alleen even uit aan het zoeken wat nochoice's stukje code precies doet

EDIT: @ nochoice. Ik ben een noob op gebied van stringbuffers en shit. Ik probeer wijs te komen uit je code en ik zal een uitspraak doen en jij moet dan maar even zeggen of ik ernaast zit: jouw strip functie kijkt alleen naar die tags, maar alles wat tussen die tags staat dan?

het resultaat wat je teruggeeft (returnbuffer) bevat alleen
XML:
1
<response-message></response-message>


En dit verwacht ik dan eigenlijk terug te krijgen:
XML:
1
2
3
4
5
6
<response-message>
    <gebruikersnaam>[EXC]NaNthor</gebruikersnaam>
    <gebruikers_id>0018</gebruikers_id>
    ....
    ....
</response-message>

[ Voor 122% gewijzigd door Deathchant op 21-07-2004 13:49 ]

Canon: EOS R6 | EF 16-35/4L IS USM | EF 70-200/2.8L IS II USM
Zeiss: 35/2 Distagon | 50/2 Makro-Planar | 85/1.4 Planar | 100/2 Makro-Planar | 135/2 Apo Sonnar


Verwijderd

Deathchant schreef op 21 juli 2004 @ 13:35:

EDIT: @ nochoice. Ik ben een noob op gebied van stringbuffers en shit. Ik probeer wijs te komen uit je code en ik zal een uitspraak doen en jij moet dan maar even zeggen of ik ernaast zit: jouw strip functie kijkt alleen naar die tags, maar alles wat tussen die tags staat dan?

het resultaat wat je teruggeeft (returnbuffer) bevat alleen
XML:
1
<response-message></response-message>


En dit verwacht ik dan eigenlijk terug te krijgen:
XML:
1
2
3
4
5
6
<response-message>
    <gebruikersnaam>[EXC]NaNthor</gebruikersnaam>
    <gebruikers_id>0018</gebruikers_id>
    ....
    ....
</response-message>
Dat zou toch ook hetgeen zijn wat ik verwacht, zo had ik het wel geschreven :> (Optimistic thinking)
Maar nu ik er nog goed over nadenk heb ik een GROTE denkfout heb gemaakt. Ik lees namelijk met een array (buffer) de inputstream uit. Stel nu dat er op de eerste read een halve regel staat en dan het begin van de start-tag (response-message) zonder de rest van de start-tag! Dat gaat natuurlijk enorm vout!

Een andere oplossing is misschien om met de StringBuffer het volledige document in te lezen als een grote String en dan gaan zoeken met de String methode(n) indexof

Maar ik wil je toch nog ff wijzen op de andere replies (XML als XML lezen is echt veel beter dan dit soort oplossingen)

  • mulder
  • Registratie: Augustus 2001
  • Laatst online: 21:13

mulder

ik spuug op het trottoir

Deathchant schreef op 21 juli 2004 @ 13:35:
dat laatste ;)
code:
1
2
3
4
5
6
7
8
<html>
<head>
<response-message>
...
..
</response-message>
...
etc
Dan moet je dus alleen de bodytext hebben, en hou je een xml string over die bv met MSXML gewoon kan worden ingelezen.

[ Voor 70% gewijzigd door mulder op 21-07-2004 14:59 ]

oogjes open, snaveltjes dicht


  • Deathchant
  • Registratie: September 2003
  • Laatst online: 22-05 16:51

Deathchant

Don't intend. Do!

Topicstarter
bedankt voor jullie kennis. Apprecieer ik zeer.

Kep zelf ook ff wat gefixt: Zo zou het ook kunnen denk ik dan:

Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
private byte[] stripDaResponse(String in)  {
    
    //  check of string voorkomt
    int begin = in.indexOf("<response-message");
    if ( begin == -1 ) { 
      // not found
      return null;
    }
    
    String fixedFront = in.substring(begin-1);
    int end = fixedFront.indexOf("</response-message>");
    if ( end == -1 ) { 
      // not found
      return null;
    }
    // <response-message> telt 14 karakters
    String fixed = fixedFront.substring(1,end + 19);
    
    // put in byteArray
    byte[] b = fixed.getBytes();
    return b;
}

dan krijg ik em idd als string door met getResponseBodyAsString. Stuk handiger dan met die Stringbuffers doen. In feite doe ik met substring gewoon alles pakken tot aan het karakter aan het einde van de <response-message> string.

[ Voor 77% gewijzigd door Deathchant op 21-07-2004 16:36 ]

Canon: EOS R6 | EF 16-35/4L IS USM | EF 70-200/2.8L IS II USM
Zeiss: 35/2 Distagon | 50/2 Makro-Planar | 85/1.4 Planar | 100/2 Makro-Planar | 135/2 Apo Sonnar

Pagina: 1