# XML Attribute auslesen



## Häcki. (19. Jun 2010)

Hallo Leute,

ich habe folgende XML-Struktur: http://www.openthesaurus.de/synonyme/search?q=Synonym&format=text/xml

Nun möchte ich in Java beispielsweise aus dem ersten Synset-Element alle Kindelemente, die "term" heißen - und von denen benötige ich jeweils das Attribut "term", speziell: dessen Wert.

Im Beispiel wäre das also folgendes, was ich gern (am liebsten) in einem Array hätte:
andere Bezeichnung, anderes Wort für, bedeutungsgleiches Wort, Ersatzwort, Synonym

Der aktuelle Ansatz (Auszug davon - das sollte ja das sein, was wichtig ist) dafür ist folgender:

```
private static void DisplayResults(Document doc) throws XPathExpressionException 
	{
		String searchTerms = "Synonym"
		NodeList results = (NodeList)xpath.evaluate("//matches/synset/term/@term", doc, XPathConstants.NODESET); 

		// Display the results header.
		System.out.println("Web results for " + searchTerms);
		System.out.println();

		// Display the Web results.
		StringBuilder builder = new StringBuilder();
		
		for(int i = 0 ; i < results.getLength(); i++)
		{
			NodeList childNodes = results.item(i).getChildNodes();

			for (int j = 0; j < childNodes.getLength(); j++) 
			{
				if(!childNodes.item(j).getLocalName().equalsIgnoreCase("DisplayUrl"))
				{
					String fieldName = childNodes.item(j).getLocalName();

                                        System.out.println(childNodes.item(j).getTextContent());
					rueckgabe[i][j] = fieldName + ":" + childNodes.item(j).getTextContent();
					builder.append(fieldName + ":" + childNodes.item(j).getTextContent());
					builder.append("\n");
				}
			}

			builder.append("\n");
		}

		System.out.println(builder.toString());
	}
```

Gibt mir bisher natürlich nur folgende Ausgabe:


> Web results for Synonym


Tipps & Tricks?


----------



## Noctarius (19. Jun 2010)

sowas?


```
package org.sourceprojects.lycia.incubator.test;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

import org.junit.Test;
import org.sourceprojects.lycia.XmlParser;
import org.sourceprojects.lycia.XmlParserBuilder.GenerationStrategy;
import org.sourceprojects.lycia.fluent.FluentBuilder;
import org.sourceprojects.lycia.incubator.annotations.Attribute;
import org.sourceprojects.lycia.incubator.annotations.ContextObject;
import org.sourceprojects.lycia.incubator.internal.generator.AnnotatedParameterReflectiveGenerator;

import static org.junit.Assert.*;
import static org.sourceprojects.lycia.fluent.FluentBuilder.*;

public class TermParserTestCase {
	private static final String XML_DATA = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<matches><synset><term term=\"foo\" /><term term=\"bar\" /><term /></synset></matches>";

	@Test
	@SuppressWarnings("unchecked")
	public void testXmlPathConfigure() throws Exception {
		Method method = getClass().getMethod("parseData", List.class,
				String.class);

		FluentBuilder<List<String>> builder = prepare();
		builder.configure(validateSchema(false));
		builder.configure(generationStrategy(GenerationStrategy.Customized,
				AnnotatedParameterReflectiveGenerator.class));
		builder.parser(xpath("//matches/synset/term[@term]", method(method,
				this)));

		XmlParser<List<String>> xmlParser = builder.build();

		xmlParser.getParserContext().setContextObject(new ArrayList<String>());

		xmlParser.parse(XML_DATA);
		List<String> values = xmlParser.getParserContext().getContextObject();

		assertEquals(2, values.size());
		assertEquals("foo", values.get(0));
		assertEquals("bar", values.get(1));
	}

	public void parseData(@ContextObject List<String> values,
			@Attribute("term") String value) {

		values.add(value);
	}

}
```


----------



## Häcki. (20. Jun 2010)

Was machst du denn an folgender Stelle?

[JAVA=41]        assertEquals(2, values.size());
        assertEquals("foo", values.get(0));
        assertEquals("bar", values.get(1));
[/code]


----------



## Noctarius (20. Jun 2010)

Ich benutze hier Lycia. Ich habe das einfach nur fix als Unittest implementiert und mit den 3 Zeilen prüfe ich, ob die aus dem Parser kommenden Werte das sind war ich vermute


----------



## Häcki. (20. Jun 2010)

Ah, nun gut okay - ich glaub den Lycia lasse ich erstmal weg. Wobei der recht interessant aussieht. Aber ehe ich mir da jetzt zig Packages wieder installieren muss (hat jemand von euch schonmal mit JADE gearbeitet? Ich hasse solche Agentensysteme ...), bleibe ich erstmal beim SAXParser. In einer freien Minute schau ich mir den Lycia mal genauer an. Danke für den Tipp!

Neue Version des Codes, der sogar mittlerweile ein wenig funktioniert:

```
import org.w3c.dom.Document;
import org.w3c.dom.*;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException; 

public class Syn2
{
    public static void main(String argv [])
    {
	    try 
	    {
	    	DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
	        DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
	        Document doc = docBuilder.parse("http://www.openthesaurus.de/synonyme/search?format=text/xml&q=Synonym");
	
	        // normalize text representation
	        doc.getDocumentElement().normalize();
	        System.out.println ("Root element of the doc is " + doc.getDocumentElement().getNodeName());
	
	        NodeList listOfSyn = doc.getElementsByTagName("synset");
	        int totalSyns = listOfSyn.getLength();
	        System.out.println("Total no of synsets: " + totalSyns);
	
	        for(int s=0; s < listOfSyn.getLength(); s++)
	        {
	            Node synsetNode = listOfSyn.item(s);
	            if(synsetNode.getNodeType() == Node.ELEMENT_NODE)
	            {
	                Element termMainElement = (Element)synsetNode;
	                NodeList termList = termMainElement.getElementsByTagName("term");
	                Element termElement = (Element)termList.item(0);
	                System.out.println(termElement.getAttribute("term"));
	            }
	        }
	    }
	    catch(SAXParseException err)
	    {
	        System.out.println ("** Parsing error" + ", line " + err.getLineNumber () + ", uri " + err.getSystemId ());
	        System.out.println(" " + err.getMessage ());
	    }
	    catch(SAXException e)
	    {
	        Exception x = e.getException();
	        ((x == null) ? e : x).printStackTrace ();
	    }
		catch(Throwable t)
		{
		    t.printStackTrace ();
		}
	    //System.exit (0);
    }
}
```

Gibt mir allerdings nur das jeweils erste Ergebnis eines jeden Synsets aus - soweit ich das nachvollziehen kann ist das wohl auch logisch (zumindest irgendwie ...).

Der "Fehler" liegt vermutlich hier:
[JAVA=26]	        for(int s=0; s < listOfSyn.getLength(); s++)
	        {
	            Node synsetNode = listOfSyn.item(s);
	            if(synsetNode.getNodeType() == Node.ELEMENT_NODE)
	            {
	                Element termMainElement = (Element)synsetNode;
	                NodeList termList = termMainElement.getElementsByTagName("term");
	                Element termElement = (Element)termList.item(0);
	                System.out.println(termElement.getAttribute("term"));
	            }
	        }[/code]

Speziell der Teil in der IF-Bedingung.
Kann mir jemand sagen, wie ich nun noch noch ALLE Terms innerhalb des jeweiligen Synset ausgegeben bekomme?
Ich muss wohl irgendwie hieran arbeiten:
Element termElement = (Element)termList.item(0);

Wie bekomme ich denn die Anzahl der TERM-Elemente ermittelt? Wenn ich das hätte, wäre es kein Problem das in einer FOR-Schleife z.B. auszugeben.
Tipps/Tricks?

Edit:
So schwer war es dann doch nicht:
[JAVA=33]	                int number = termList.getLength();
	                for(int i = 0; i < number; i++)
	                {
		                Element termElement = (Element)termList.item(i);
		                System.out.println(termElement.getAttribute("term"));
	                }[/code]


----------



## Noctarius (20. Jun 2010)

Hast du einfach mal versucht, den XPath Ausdruck aus meinem Code oben zu nutzen  Der ist nämlich ganz leicht anders.


----------

