使用 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的主要内容,如果未能解决你的问题,请参考以下文章

xml 使用 sax 解析器从子标签解析数据

jaxp解析器——sax

使用 SAX 解析器解析自关闭 XML 标记时遇到问题

如何使用 SAX 解析器解析 XML

使用 SAX 解析器,如何解析具有相同名称标签但元素不同的 xml 文件?

如何使用 SAX 解析器在 XML 中添加元素?