attr...">

How to parse xml on hashmap?

I have an xml example that I want to parse

<?xml version="1.0" encoding="utf-8"?> <Details> <detail-a> <detail> attribute 1 of detail a </detail> <detail> attribute 2 of detail a </detail> <detail> attribute 3 of detail a </detail> </detail-a> <detail-b> <detail> attribute 1 of detail b </detail> <detail> attribute 2 of detail b </detail> </detail-b> </Details> 

I would like a method to be written from this xml that will parse it on hashmap, that the key is a string and the value is a list of strings.

for example: key "detail a" value = {"attribute 1 of part a", "attribute 2 of part a", "attribute 3 of part a"}

etc.

What is the best way to do this? because I was embarrassed: \

I got so far as to try to print details-a and detail-b, but I got lost ...

 public static void main(String[] args) { // TODO Auto-generated method stub DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance(); DocumentBuilder builder; try { builder = factory.newDocumentBuilder(); File f= new File("src/Details.xml"); Document doc=builder.parse(f); Element root=doc.getDocumentElement(); NodeList children=root.getChildNodes(); for(int i=0;i<children.getLength();i++) { Node child=children.item(i); if (child instanceof Element) { Element childElement=(Element) child; Text textNode=(Text)childElement.getFirstChild(); String text=textNode.getData().trim(); System.out.println(text); } } } catch (ParserConfigurationException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } catch (SAXException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } 
+6
source share
2 answers

Use JAXB to read from xml and save it in a custom object.

User class of the object:

 import java.util.List; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElementWrapper; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; @XmlRootElement(name = "Details") @XmlType(propOrder = { "detailA", "detailB" }) public class Details { private List<String> detailA; private List<String> detailB; public void setDetailA(List<String> detailA) { this.detailA = detailA; } @XmlElementWrapper(name = "detail-a") @XmlElement(name = "detail") public List<String> getDetailA() { return detailA; } public void setDetailB(List<String> detailB) { this.detailB = detailB; } @XmlElementWrapper(name = "detail-b") @XmlElement(name = "detail") public List<String> getDetailB() { return detailB; } } 

Extract the data from your xml into the object, then add the contents to the map as desired:

 public static void main(String[] args) throws JAXBException, FileNotFoundException { System.out.println("Output from our XML File: "); JAXBContext context = JAXBContext.newInstance(Details.class); Unmarshaller um = context.createUnmarshaller(); Details details = (Details)um.unmarshal(new FileReader("details.xml")); List<String> detailA = details.getDetailA(); List<String> detailB = details.getDetailB(); Map<String, String[]> map = new HashMap<String, String[]>(); map.put("detail-a", detailA.toArray(new String[detailA.size()])); map.put("detail-b", detailB.toArray(new String[detailB.size()])); for (Map.Entry<String, String[]> entry : map.entrySet()) { //key "detail a" value={"attribute 1 of detail a","attribute 2 of detail a","attribute 3 of detail a"} System.out.print("Key \"" +entry.getKey()+"\" value={"); for(int i=0;i<entry.getValue().length;i++){ if(i!=entry.getValue().length-1){ System.out.print("\""+entry.getValue()[i]+"\","); } else{ System.out.print("\""+entry.getValue()[i]+"\"}"); } } System.out.println(); } } 

The output will be:

  Output from our XML File: 
 Key "detail-a" value = {"attribute 1 of detail a", "attribute 2 of detail a", "attribute 3 of detail a"}
 Key "detail-b" value = {"attribute 1 of detail b", "attribute 2 of detail b"}

As a side note: this will only work for the xml that you provided as input in your question, if you need to add more details, like detail-c , etc., you should also define them in your custom object.

XML Used:

 <?xml version="1.0" encoding="utf-8"?> <Details> <detail-a> <detail>attribute 1 of detail a</detail> <detail>attribute 2 of detail a</detail> <detail>attribute 3 of detail a</detail> </detail-a> <detail-b> <detail>attribute 1 of detail b</detail> <detail>attribute 2 of detail b</detail> </detail-b> </Details> 
+3
source

I can't resist presenting a much shorter solution using XMLBeam , which works with any number of detail-x subelements.

 public class Tetst { @XBDocURL("resource://test.xml") public interface Projection { @XBRead("name()") String getName(); @XBRead("./detail") List<String> getDetailStrings(); @XBRead("/Details/*") List<Projection> getDetails(); } @Test public void xml2Hashmap() throws IOException { HashMap<String, List<String>> hashmap = new HashMap<String, List<String>>(); for (Projection p : new XBProjector().io().fromURLAnnotation(Projection.class).getDetails()) { System.out.println(p.getName() + ": " + p.getDetailStrings()); hashmap.put(p.getName(), p.getDetailStrings()); } } } 

Will print

 detail-a: [ attribute 1 of detail a , attribute 2 of detail a , attribute 3 of detail a ] detail-b: [ attribute 1 of detail b , attribute 2 of detail b ] 

for your example test.xml and populate the hashmap.

+2
source

Source: https://habr.com/ru/post/979858/


All Articles