使用 SAX 解析器解析 Xml

Posted

技术标签:

【中文标题】使用 SAX 解析器解析 Xml【英文标题】:Parsing Xml with SAX Parser 【发布时间】:2012-08-27 21:17:29 【问题描述】:

我正在尝试使用 SAX 解析器解析 xml 文件。 我需要获取属性及其起始元素的值

<?xml version="1.0" encoding="ISO-8859-1" ?>
<API type="Connection">
<INFO server="com.com" function="getAccount2" />
<RESULT code="0">Operation Succeeded</RESULT>
<RESPONSE numaccounts="1">
<ACCOUNT login="fa051981" skynum="111111" maxaliases="1" creationdate="Fri Nov 16 00:59:59 2001"    password="pass" type="2222" status="open" mnemonic="32051981" ratelimit="0">
    <CHECKATTR />
    <REPLYATTR>Service-Type = Frames-User, Framed-Protocol = PPP, Framed-Routing = None</REPLYATTR>
    <SETTINGS bitval="4" status="open" />
    <SETTINGS bitval="8192" status="open" session_timeout="10800" />
    <SETTINGS bitval="32768" status="open" cisco_address_pool="thepool" />
    <ALIASES numaliases="0" />
</ACCOUNT>
</RESPONSE>
</API>

在这个 xml 中,我需要获取设置标签/开始元素属性及其值。

这些属性是动态的,所以我正在尝试制作它们的地图。我是 SAX 解析器的新手。

到目前为止我的java代码:

public void startElement(String s, String s1, String elementName, Attributes attributes) throws SAXException 

    if (elementName.equalsIgnoreCase(GenericConstants.INFO)) 
        this.searchRaidusBean.setServer(attributes.getValue(GenericConstants.SERVER));
        this.searchRaidusBean.setFunction(attributes.getValue(GenericConstants.FUNCTION));
    
    if (elementName.equalsIgnoreCase(GenericConstants.RESULT)) 
        this.searchRaidusBean.setResultCode(attributes.getValue(GenericConstants.CODE));
    

    if (elementName.equalsIgnoreCase(GenericConstants.ACCOUNT)) 
        this.searchRaidusBean.setLoginId(attributes.getValue(GenericConstants.LOGIN));
    
    if (elementName.equalsIgnoreCase(GenericConstants.ACCOUNT)) 
        this.searchRaidusBean.setSkyNum(attributes.getValue(GenericConstants.SKYNUM));
    
    if (elementName.equalsIgnoreCase(GenericConstants.ACCOUNT)) 
        this.searchRaidusBean.setMaxAliases(attributes.getValue(GenericConstants.MAXALIASES));
    
    if (elementName.equalsIgnoreCase(GenericConstants.ACCOUNT)) 
        this.searchRaidusBean.setCreationDate(attributes.getValue(GenericConstants.CREATION_DATE));
    
    if (elementName.equalsIgnoreCase(GenericConstants.ACCOUNT)) 
        this.searchRaidusBean.setType(attributes.getValue(GenericConstants.TYPE));
    
    if (elementName.equalsIgnoreCase(GenericConstants.ACCOUNT)) 
        this.searchRaidusBean.setStatus(attributes.getValue(GenericConstants.STATUS));
    
    if (elementName.equalsIgnoreCase(GenericConstants.ACCOUNT)) 
        this.searchRaidusBean.setMnemonic(attributes.getValue(GenericConstants.MNEMONIC));
    
    if (elementName.equalsIgnoreCase(GenericConstants.ACCOUNT)) 
        this.searchRaidusBean.setRateLimit(attributes.getValue(GenericConstants.RATELIMIT));
    
    if (elementName.equalsIgnoreCase(GenericConstants.SETTINGS)) 
        //this.searchRaidusBean.getBitval().add(attributes.getValue(GenericConstants.BITVAL));
        System.out.println(attributes);
        //stuck here
    
    if (elementName.equalsIgnoreCase(GenericConstants.ALIASES)) 
        this.tempKey = attributes.getValue(GenericConstants.MNEMONIC);
    




public void endElement(String str1, String str2, String element) throws SAXException 
    if (element.equalsIgnoreCase(GenericConstants.RESULT)) 
        this.searchRaidusBean.setResultMessage(this.tempValue);
    
    if (element.equalsIgnoreCase(GenericConstants.ALIASES)) 
        if (!StringUtils.isBlank(this.tempKey)) 
            this.searchRaidusBean.getAlias().put(this.tempKey, this.tempValue);
        
    



public void characters(char[] charArray, int i, int j) throws SAXException 
    this.tempValue = new String(charArray, i, j);

【问题讨论】:

有很多关于 SAX 解析的教程。 SO不是您通过发布问题获得程序的地方。在发帖寻求帮助之前,您需要展示自己的努力。 另外,将来,您尝试过的一些代码示例会有所帮助,因此我们不会浪费彼此的时间来寻找错误的代码路径 除非你真的需要使用 SAX(例如因为作业分配或过时的 java 版本),否则 pull 解析器将是更好更容易的替代方案 是 SAX 解析需求还是您打开更好的东西 【参考方案1】:

如果您使用的是DefaultHandler,那么您将收到startElement 事件。

此方法带有Attributes 作为其参数之一。

您需要使用getIndex(String) 获取命名属性的索引,使用getValue(int) 获取所述属性的值。

正如 Nambari 所指出的,互联网上有数百个教程,关于 SO 主题的帖子不止几篇(我在周末回答了一篇)。

更新

我建议它应该看起来像这样(我还没有测试过)

public void startElement(String uri, String localName, String elementName, Attributes attributes) throws SAXException 

    if (elementName.equalsIgnoreCase(GenericConstants.INFO)) 
        this.searchRaidusBean.setServer(attributes.getValue(GenericConstants.SERVER));
        this.searchRaidusBean.setFunction(attributes.getValue(GenericConstants.FUNCTION));
    
    if (elementName.equalsIgnoreCase(GenericConstants.RESULT)) 
        this.searchRaidusBean.setResultCode(attributes.getValue(GenericConstants.CODE));
    

    if (elementName.equalsIgnoreCase(GenericConstants.ACCOUNT)) 
        this.searchRaidusBean.setLoginId(attributes.getValue(GenericConstants.LOGIN));
        this.searchRaidusBean.setSkyNum(attributes.getValue(GenericConstants.SKYNUM));
        this.searchRaidusBean.setMaxAliases(attributes.getValue(GenericConstants.MAXALIASES));
        this.searchRaidusBean.setCreationDate(attributes.getValue(GenericConstants.CREATION_DATE));
        this.searchRaidusBean.setType(attributes.getValue(GenericConstants.TYPE));
        this.searchRaidusBean.setStatus(attributes.getValue(GenericConstants.STATUS));
        this.searchRaidusBean.setMnemonic(attributes.getValue(GenericConstants.MNEMONIC));
        this.searchRaidusBean.setRateLimit(attributes.getValue(GenericConstants.RATELIMIT));
    

    if (elementName.equalsIgnoreCase(GenericConstants.SETTINGS)) 

        for (int index = 0; index < attributes.getLength(); index++) 

            String attName = attributes.getLocalName(index);
            String value = attributes.getValue(index);

            map.put(attName, value);

        

    

    if (elementName.equalsIgnoreCase(GenericConstants.ALIASES)) 
        this.tempKey = attributes.getValue(GenericConstants.MNEMONIC);
    


已更新测试示例

我带了你数据(来自 OP)并通过以下处理程序运行它

DefaultHandler handler = new DefaultHandler() 
    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException 

        if (qName.equalsIgnoreCase("settings")) 

            System.out.println("Parse settings attributes...");

            for (int index = 0; index < attributes.getLength(); index++) 

                String aln = attributes.getLocalName(index);
                String value = attributes.getValue(index);

                System.out.println("    " + aln + " = " + value);


            

        

    
;

我得到了以下输出

Parse settings attributes...
    bitval = 4
    status = open
Parse settings attributes...
    bitval = 8192
    status = open
    session_timeout = 10800
Parse settings attributes...
    bitval = 32768
    status = open
    cisco_address_pool = thepool

所以我不知道你在做什么。

【讨论】:

在第一篇文章中添加了代码。我已经通过网络教程和谷歌搜索。把这个特例就不讨论了。 但是上面的 for 循环会获取所有属性(包括从父节点级联的属性)。因此它将包含帐户属性,例如登录名,sknum。 是我自己还是 SAX 解析代码看起来很自虐? @vtd-xml-author Sax 使用访问者模式,并不是我首选的 xml 解析方法 @vtd-xml-author 不,转到 Json

以上是关于使用 SAX 解析器解析 Xml的主要内容,如果未能解决你的问题,请参考以下文章