使用SJXP将属性值AND节点值解析为同一个userobject

时间:2012-12-13 15:50:52

标签: java xml xml-parsing sjxp

我试图利用Simple Java XML Parser (SJXP)但遇到了我需要解析为数据类的XML的问题。

data.xml中

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE SYSTEM "local-1.2.2.dtd" >
<data>
    <article>
        <field name="name" type="text">HOTELS</field>
        <field name="name_de" type="text">HOTELS</field>
        <field name="name_zh" type="text">酒店</field>
        <field name="color" type="text">6,68,109,0.85</field>
        <field name="textcolor" type="text">255,255,255,1</field>
    </article>
 <!-- 20000 more articles ... -->
</data>

我试图这样做:

XmlHandler.java

private Map<String, Category> categoryMap;

private XMLParser<Category> categoryParser = new XMLParser<Category>(
        new DefaultRule<Category>(IRule.Type.CHARACTER, "/data/article") {
            @Override
            public void handleParsedCharacters(XMLParser<Category> parser, String text, Category category) {

                Log.d("XmlHandler", "Hello");
                if (category != null) {
                    categoryMap.put(category.getName(Category.LANG.EN), category);
                    Log.d("XmlHandler", "Saved category to map. New count="+categoryMap.values().size());
                    category.reset();
                } else {
                    category = new Category();
                    Log.d("XmlHandler", "Creating a new category");
                }
            }
        },
        new CategoryNameRule()
);


private class CategoryNameRule extends DefaultRule<Category> {

    private String nameKey = "";

    public CategoryNameRule() {
        super(Type.ATTRIBUTE, "/data/article/field", "name");
    }

    @Override
    public void handleParsedAttribute(XMLParser parser, int index,
                                      String value, Category category) {
        nameKey = value;
    }

    @Override
    public void handleParsedCharacters(XMLParser parser, String text, Category category) {

        Log.d("XmlHandler", "Handling nameKey="+nameKey);

        if(nameKey == null || nameKey.length() == 0){
            return;
        }else if( "name".equals(nameKey)){
           category.setName(Category.LANG.EN, text);
        }else if( "name_de".equals(nameKey)){
           category.setName(Category.LANG.DE, text);
        }else if( "name_zh".equals(nameKey)){
           category.setName(Category.LANG.ZH, text);
        }else if( "color".equals(nameKey)){
           category.colorBackground = getConvertedColor(text);
        }else if( "textcolor".equals(nameKey)){
           category.colorForeground = getConvertedColor(text);
        }

    }
}

问题是我的hashmap在整个文档被解析后变空了,我不知道为什么。我的猜测是我组合了IRule.Type.CHARACTER&amp; IRule.Type.ATTRIBUTE,但我不知道如何实现。

有任何想法/经验吗?

1 个答案:

答案 0 :(得分:0)

的Stefan, 我很抱歉错过了这个问题(我在搜索其他内容时偶然发现了谷歌)。

这里有一些混乱点,所以让我澄清,然后概述我将如何推荐解决这个问题(假设你找不到办法,但我意识到这是3个月前)

首先,你是对的,你需要CHARACTER规则和ATTRIBUTE规则的组合。 CHARACTER规则将为您提供标记之间的内容,例如:

<tag>this is CHARACTER data</tag>

其次,您的规则应该定位包含您需要的数据的标记,在上面的示例中,看起来您没有获得任何差异化数据,直到您到达/ data / article / field级别(单个字段包含两个属性)和你想要的字符)

看起来像你关键(打开标签),告诉你什么时候输入新文章,因此你知道你正在收集特定的,独特的文章的字段信息。在这种情况下,当您点击开始标记时,您实际上可以使用TAG规则进行归档,因此您可以执行一些逻辑,例如在HashMap中为即将解析的新文章创建新记录。

最后,您传递给处理程序的 Category 参数是 pass-through 用户变量。

这意味着您可以调用Parse方法:

XMLParser<List<Article>> p = new XMLParser<List<Article>>(... stuff ...);
List<Article> articleList = new ArrayList<Article>();

p.parse(input, articleList);

这允许所有处理程序可以直接访问您的articleList,以便它们可以直接在其中解析/存储信息,因此当调用解析(...)返回时,您知道您的列表是最新的并且已更新。

如果没有向userObject字段中的parse方法传递任何内容,则处理程序将全部收到 null 参数。

您检查类别的使用让我感到困惑,并让我觉得您在调用处理程序时期望获得更改值,但实际情况并非如此。我只想澄清一下。

<强>摘要

我认为您完美的解析器设计将包含3条规则:

  • / data / article TAG规则 - 遇到START文章标记时(以及可选的CLOSE文章标记时)执行某些操作。
  • / data / article / field CHARACTER规则 - 存储字段的已解析字符数据。
  • / data / article / field ATTRIBUTE rule - 存储该字段的已解析属性数据。

我希望有所帮助!