Как распарсить xml с повторяющимися тэгами в List?
Имеется xml с повторяющимися тэгами, примерно такой:
public class Main {
public static void main(String[] args) throws ParserConfigurationException {
String xmlString = "<abc:Body>\n" +
" <abc:AssyData>\n" +
" <abc:Order>1</abc:Order>\n" +
" <abc:Name>A</abc:Name>\n" +
" </abc:AssyData>\n" +
" <abc:AssyData>\n" +
" <abc:Order>2</abc:Order>\n" +
" <abc:Name>B</abc:Name>\n" +
" </abc:AssyData>\n" +
" <abc:AssyData>\n" +
" <abc:Order>3</abc:Order>\n" +
" <abc:Name>C</abc:Name>\n" +
" </abc:AssyData>\n" +
"</abc:Body>";
List<String> orders = new ArrayList<String>();
List<String> names = new ArrayList<String>();
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
try {
dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = convertStringToXml(xmlString);//IDOC это мой XML на диске
doc.getDocumentElement().normalize();
NodeList list = doc.getElementsByTagName("abc:Body");
for (int temp = 0; temp < list.getLength(); temp++) {
Node node = list.item(temp);
if(node.getNodeType() == Node.ELEMENT_NODE) {
Element element = (Element) node;
orders.add(element.getElementsByTagName("abc:Order").item(0).getTextContent());
names.add(element.getElementsByTagName("abc:Name").item(0).getTextContent());
}
}
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(orders);
System.out.println(names);
}
private static Document convertStringToXml(String xmlString) {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
try {
dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
DocumentBuilder builder = dbf.newDocumentBuilder();
Document doc = builder.parse(new InputSource(new StringReader(xmlString)));
return doc;
} catch (ParserConfigurationException | IOException | SAXException e) {
throw new RuntimeException(e);
}
}
}
На выходе получаю только значения
order = 1;
name = A;
то есть первых элементов А нужно получать значения всех элементов по тегу и записывать их в листы, что бы было:
List<String> orders = [1,2,3]
List<String> names = [A,B,C]
И так далее, днина документа может быть разной. Помогите плиз) (java ee 5, лямбд, стримов нет)
Ответы (1 шт):
Используйте List::add для добавления в соответствуюшие списки, для этого не нужно ни лямбд, ни стримов.
Также, вероятно, имеет смысл не разбивать данные по отдельным спискам, а использовать объект с двумя указанными полями типа такого AssyData(String name, String order) и иметь отдельный список для него.
Главная ошибка кода, представленного в вопросе, в том, что в переменную list вычитывается единственный корневой элемент документа abc:Body (разумеется, длина такого списка равна 1), а не список соответствующих элементов AssyData длиной 3.
Также были проблемы с компиляцией кода из-за неправильных названий методов Document::getElementsByTagName; Element::getElementsByTagName; Node::getTextContent
// ...
NodeList list = doc.getElementsByTagName("abc:AssyData"); // вместо abc:Body
List<AssyData> data = new ArrayList<AssyData>(); // diamond operator since Java 7
for (int temp = 0; temp < list.getLength(); temp++) {
Node node = list.item(temp);
if (node.getNodeType() == Node.ELEMENT_NODE) {
Element element = (Element) node;
order = element.getElementsByTagName("abc:Order").item(0).getTextContent();
name = element.getElementsByTagName("abc:Name").item(0).getTextContent();
// просто добавьте элементы в нужные списки
orders.add(order);
names.add(name);
data.add(new AssyData(name, order));
}
}
System.out.println(orders);
System.out.println(names);