簡體   English   中英

如何使用LinkedHashMap解析包含多個標簽的xml文件?

[英]How to parse xml file containing multiple tags using LinkedHashMap?

我想構建一個解析器來解析JavaXML文件。 正如您在下面的代碼中看到的那樣,我正在使用LinkedHashMap訪問所需的值FirstMiddleLast

我的問題是我有包含多個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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM