[英]How to parse xml file containing multiple tags using LinkedHashMap?
我想構建一個解析器來解析Java
的XML
文件。 正如您在下面的代碼中看到的那樣,我正在使用LinkedHashMap
訪問所需的值First
, Middle
和Last
。
我的問題是我有包含多個Person
標簽的NameList
標簽,而到目前為止, LinkedHashMap
在我的示例中僅給我最后一個Person
(輸出):
given: Ghi family: Tom given: Jkl family: Mary
如何使用LinkedHashMap
方法訪問其他兩個(Karl Abc,Thomas Def)?
這是我的XML
文件:
<Sources>
<Source>
<Year>2019</Year>
</Source>
<Source>
<Title>Blablabla</Title>
<Author>
<BookAuthor>
<NameList>
<Person>
<Last>Karl</Last>
<First>Abc</First>
</Person>
<Person>
<Last>Thomas</Last>
<First>Def</First>
</Person>
<Person>
<Last>Tom</Last>
<First>Ghi</First>
</Person>
</NameList>
</BookAuthor>
</Author>
</Source>
<Source>
<Author>
<Editor>
<NameList>
<Person>
<Last>Mary</Last>
<First>Jkl</First>
</Person>
</NameList>
</Editor>
</Author>
</Source>
這是我的代碼:
private static void XmlFileParser() throws IOException {
InputStream xmlFile = Publication.class.getClassLoader().getResourceAsStream("test.xml");
ObjectMapper mapper = new XmlMapper();
// Configure
mapper
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
try {
Object[] deserializedData = mapper.readValue(xmlFile, Object[].class);
for (Object element : deserializedData) {
if (element instanceof LinkedHashMap) {
LinkedHashMap<String, Object> el = (LinkedHashMap<String, Object>) element;
if ((el.get("Author")) == null) {
continue;
} else {
// Last -> family
// First, Middle -> given
if (((LinkedHashMap) el.get("Author")).get("Author") instanceof LinkedHashMap && ((((LinkedHashMap) ((LinkedHashMap) el
.get("Author")).get("Author")).get("NameList")) != null)) {
Object first = ((LinkedHashMap) ((LinkedHashMap) ((LinkedHashMap) ((LinkedHashMap) el.get(
"Author")).get("Author")).get("NameList")).get("Person")).get("First");
Object middle = ((LinkedHashMap) ((LinkedHashMap) ((LinkedHashMap) ((LinkedHashMap) el.get(
"Author")).get("Author")).get("NameList")).get("Person")).get("Middle");
if (first != null || middle != null) {
System.out.println("given: " + evaluateGiven(first, middle));
}
Object family = ((LinkedHashMap) ((LinkedHashMap) ((LinkedHashMap) ((LinkedHashMap) el.get(
"Author")).get("Author")).get("NameList")).get("Person")).get("Last");
System.out.println("family: " + family);
} else if (((LinkedHashMap) el.get("Author")).get("Editor") instanceof LinkedHashMap && ((((LinkedHashMap) ((LinkedHashMap) el
.get("Author")).get("Editor")).get("NameList")) != null)) {
Object first = ((LinkedHashMap) ((LinkedHashMap) ((LinkedHashMap) ((LinkedHashMap) el.get(
"Author")).get("Editor")).get("NameList")).get("Person")).get("First");
Object middle = ((LinkedHashMap) ((LinkedHashMap) ((LinkedHashMap) ((LinkedHashMap) el.get(
"Author")).get("Editor")).get("NameList")).get("Person")).get("Middle");
if (first != null || middle != null) {
System.out.println("given: " + evaluateGiven(first, middle));
}
Object family = ((LinkedHashMap) ((LinkedHashMap) ((LinkedHashMap) ((LinkedHashMap) el.get(
"Author")).get("Editor")).get("NameList")).get("Person")).get("Last");
System.out.println("family: " + family);
}
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
我的助手班:
private static String evaluateGiven(Object first, Object middle) {
if (first == null) {
first = "";
} else if (middle == null) {
middle = "";
}
return first.toString() + " " + middle.toString();
}
由於我的代碼被炸毀,您知道如何將其縮小嗎?
我會很高興獲得一些幫助。
謝謝!
通常,列表不容易處理,並且當我們不使用POJO
結構時,我們需要編寫自定義反序列化器,它將使用Streaming API讀取內部列表對象。 在下面,您可以找到針對Author
類的帶有自定義反序列化器的簡單POJO
模型:
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Stream;
public class XmlMapperApp {
public static void main(String[] args) throws Exception {
File xmlFile = new File("./resource/test.xml").getAbsoluteFile();
XmlMapper xmlMapper = new XmlMapper();
xmlMapper.setDefaultUseWrapper(false);
xmlMapper.setPropertyNamingStrategy(PropertyNamingStrategy.UPPER_CAMEL_CASE);
Source[] sources = xmlMapper.readValue(xmlFile, Source[].class);
Stream.of(sources)
.filter(s -> Objects.nonNull(s.getAuthor()))
.map(s -> s.getAuthor().getPersons())
.filter(a -> !a.isEmpty())
.forEach(System.out::println);
}
}
class AuthorJsonDeserializer extends JsonDeserializer<Author> {
@Override
public Author deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
p.nextToken(); // Skip START_OBJECT
Author author = new Author();
author.setType(p.getText());
author.setPersons(new ArrayList<>());
JsonToken token;
while ((token = p.currentToken()) != JsonToken.END_OBJECT) {
if (token == JsonToken.FIELD_NAME) {
String name = p.getText();
if ("Person".equals(name)) {
p.nextToken();
author.getPersons().add(p.readValueAs(Person.class));
}
}
p.nextToken();
}
p.nextToken(); // Skip END_OBJECT
p.nextToken(); // Skip END_OBJECT
return author;
}
}
class Source {
private int year;
private String title;
private Author author;
// getters, setters, toString
}
@JsonDeserialize(using = AuthorJsonDeserializer.class)
class Author {
private String type;
private List<Person> persons;
// getters, setters, toString
}
class Person {
private String last;
private String first;
// getters, setters, toString
}
上面的代碼打印:
[Person{last='Karl', first='Abc'}, Person{last='Thomas', first='Def'}, Person{last='Tom', first='Ghi'}]
[Person{last='Mary', first='Jkl'}]
您可以打印整個Source
實例: Stream.of(sources).forEach(System.out::println);
並且您應該看到:
Source{year=2019, title='null', author=null}
Source{year=0, title='Blablabla', author=Author{type='BookAuthor', persons=[Person{last='Karl', first='Abc'}, Person{last='Thomas', first='Def'}, Person{last='Tom', first='Ghi'}]}}
Source{year=0, title='null', author=Author{type='Editor', persons=[Person{last='Mary', first='Jkl'}]}}
另請參閱: 解析時如何忽略外包裝?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.