如何使用 SimpleXML 解析 XML 并将其存储在 Map 中?

How to parse XML and store it in a Map with SimpleXML?

我在使用简单的 xml 框架解析 xml 时遇到问题。我想在 Map/hashMap 中存储类别 ID 和锦标赛列表,我该怎么做?我遵循了关于简单 xml 的教程,但它对我不起作用。

我将它存储在这样的列表中:

 @ElementList(entry = "Category", inline = true, required = false)
List<Category> category;

但现在我想将其存储在地图中。

这里是xml:

我遵循的教程:

感谢任何帮助,tnx。

问题是您正在尝试创建类似 Map<String, <List<Tournament>> 的结构,而使用 ElementMap 注释似乎无法实现。您需要某种 ElementMapList 注释。或许您可以 file an issue,Gallagher 先生可以补充一点。

@ElementList@ElementMap 这样的 Annoations 不可能,但使用 Converter 仍然是 (好)选项

这样做意味着:为 Tournaments 实现 Converter合并 Category-Id / Tournament List 对。

这是如何完成的:


首先是必要的(数据-)classes.

锦标赛:

@Root(name = "Tournament")
public class Tournament
{
    @Text
    private String data;

    public Tournament(String data)
    {
        this.data = data;
    }

    private Tournament() { /* Required */ }

    // ...
}

注意: 我给了 Tournament 一些数据字符串,因为没有显示真实数据。然而,实际上它包含什么数据并不重要。

类别:

@Root(name = "Category")
public class Category
{
    private String id;

    // ...
}

锦标赛

@Root(name = "Tournaments")
@Convert(TournamentsConverter.class) // Specify the Converter used for this class
public class Tournaments
{
    private Map<String, List<Tournament>> tournaments;

    public Tournaments()
    {
        tournaments = new HashMap<>();
    }


    protected void put(String id, List<Tournament> tournaments)
    {
        this.tournaments.put(id, tournaments);
    }

    // ...
}

@Convert将使用下面的Converter进行Tournaments的序列化/反序列化。我没有在这个例子中实现序列化部分(虽然不难)。

重要提示: @Convert 需要一个 AnnotationStrategy(参见下面的示例)!

锦标赛转换器

public class TournamentsConverter implements Converter<Tournaments>
{
    private final Serializer serializer = new Persister();


    @Override
    public Tournaments read(InputNode node) throws Exception
    {
        Tournaments tournaments = new Tournaments();
        InputNode childNode = node.getNext();

        // Iterate over all childs of 'Tournaments'
        while( childNode != null )
        {
            if( childNode.getName().equals("Category") == true )
            {
                final String categoryId = childNode.getAttribute("category_id").getValue();

                List<Tournament> tournamentList = new ArrayList<>();
                InputNode child = childNode.getNext();

                // Iterate over all childs of 'Category'
                while( child != null )
                {
                    // Use a Serializer to read the nodes data
                    Tournament tournament = serializer.read(Tournament.class, child);
                    tournamentList.add(tournament);

                    child = childNode.getNext();
                }

                // Insert the Id / Tournament's pair
                tournaments.put(categoryId, tournamentList);
            }

            childNode = node.getNext();
        }

        return tournaments;
    }


    @Override
    public void write(OutputNode node, Tournaments value) throws Exception
    {
        // Implement as needed
        throw new UnsupportedOperationException("Not supported yet.");
    }

}

所有"magic"都由转换器完成:

  1. 迭代所有 Tournaments 个子节点
  2. 如果是 Category
    1. 得到id
    2. 遍历所有子项并将 Tournament 添加到列表
    3. id / Tournament 的列表添加到结果 Tournaments

如上所示,可以使用 Serializer 对节点进行(反)序列化。无需手动实施。

例子

最后,举个例子。请注意 AnnotationStrategy.

Serializer ser = new Persister(new AnnotationStrategy());

final String xml = "<Tournaments>\n"
        + "   <Category category_id=\"289\">\n"
        + "      <Tournament>aaaa</Tournament>\n"
        + "   </Category>\n"
        + "   <Category category_id=\"32\">\n"
        + "      <Tournament>bbbd</Tournament>\n"
        + "      <Tournament>cccc</Tournament>\n"
        + "   </Category>\n"
        + "</Tournaments>";

Tournaments t = ser.read(Tournaments.class, xml);

System.out.println(t);

输出:
使用生成的 toString() 添加到每个 class.

Tournaments{tournaments={289=[Tournament{data=aaaa}], 32=[Tournament{data=bbbd}, Tournament{data=cccc}]}}