最新消息:20210816 当前crifan.com域名已被污染,为防止失联,请关注(页面右下角的)公众号

【已解决】Android中用DOM方式解析xml时使用getElementsByTagName去获得节点结果为空

Android crifan 4903浏览 0评论

【问题】

折腾:

【未解决】Android中解析/res/raw文件夹下面的xml文件

时,试了试下面代码:

	public static ArrayList<XmlItem> getXmlItems(InputStream inputStream, String tag){
		ArrayList<XmlItem> xmlItemList = new ArrayList<XmlItem>();
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();  
        DocumentBuilder builder;
		try {
			builder = factory.newDocumentBuilder();
	        Document document = builder.parse(inputStream);
	        Element root = document.getDocumentElement();

	        NodeList nodeList = root.getElementsByTagName(tag);
	        //NodeList nodeList = root.getElementsByTagNameNS(namespaceURI, localName)(tag);
	        for(int idx = 0; idx < nodeList.getLength(); idx++){
	        	Node curNode = nodeList.item(idx);
	        	String nodeName = curNode.getNodeName(); 
	        }
		} catch (ParserConfigurationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SAXException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return xmlItemList;
	}
    
	//public String getUniversalDataGroup() {
	public UIDataGroup getUniversalDataGroup() {
		UIDataGroup uiDataGroup = new UIDataGroup();
		
		//parse xml file to UIDataGroup

		String menuTag = "Menu";
		//String tabMenuTag = "TabMenu";
        //ArrayList<XmlItem> rootMenuItemList= XmlHelper.getXmlItems(groupMenuFilename, menuTag,null);
        //XmlItem rootMenuItem = 

        InputStream inputStream = AppContext.getInstance().getResources().openRawResource(R.raw.groupmenu);
        //ArrayList<XmlItem> rootMenuItemList= XmlHelper.getXmlItems(inputStream, menuTag,null);
        ArrayList<XmlItem> rootMenuItemList= XmlHelper.getXmlItems(inputStream, menuTag);

		return uiDataGroup;
	}

结果用getElementsByTagName去获得对应的xml:

<?xml version="1.0" encoding="UTF-8"?>
<Menu>
	<TabMenu Label="HART">
		......
	</TabMenu>
	<TabMenu Label="Device">
		......
	</TabMenu>
	......
</Menu>

竟然得到是空的NodeList:

getElementsByTagName return empty node list

 

【解决过程】

1.使用自动提示,看了看,root还有另外一个函数:

public abstract Attr getAttributeNodeNS (String namespaceURI, String localName)

Added in API level 1

Retrieves an Attr node by local name and namespace URI.

Per [XML Namespaces] , applications must use the value null as the namespaceURI parameter for methods if they wish to have no namespace.

Parameters

namespaceURI

The namespace URI of the attribute to retrieve.

localName

The local name of the attribute to retrieve.

Returns
  • The Attr node with the specified attribute local name and namespace URI or null if there is no such attribute.
Throws

DOMException

NOT_SUPPORTED_ERR: May be raised if the implementation does not support the feature "XML" and the language exposed through the Document does not support XML Namespaces (such as [HTML 4.01]).

但是不知道:

是不是由于namespace的原因

以及如何获得当前的namespace(好像当然xml中没有什么namespace)

2.参考:

xml – GetElementsByTagName returns empty list – Stack Overflow

xml – android getElementsByTagName returns empty list – Stack Overflow

没看到解决办法。

3.后来看到:

Element | Android Developers

的提示,貌似是可以通过:

root的另外一个函数:

getNamespaceURI()

去获得当然namespace,然后再去试试:

	        //NodeList nodeList = root.getElementsByTagName(tag);
	        String namespaceURI = root.getNamespaceURI();
	        NodeList nodeList = root.getElementsByTagNameNS(namespaceURI, tag);

看看结果如何,调试发现得到的namespace也是null。

所以还是无法获得对应的我要的内容。

4.后来看到:

android getElementsByTagName returns empty list (1 answer)

还是没解决办法。

5.参考:

Element.getElementsByTagName – Web API Interfaces | MDN

去看看document是否有“getElementById”,不过待会再试。

6.不过试了试,去查找,非root节点,找其他的tag:

	        //NodeList nodeList = root.getElementsByTagName(tag);
	        NodeList nodeList = root.getElementsByTagName("TabMenu");

就可以找到了:

search another tabmenu tag can found 4 node list

7.突然想到了,是不是:

当然已经是处于root节点了,所以无法获得对应的root节点的tag?

但是可以(通过tag去)获得root节点其下的其他的节点?

所以,去验证一下此想法:

			builder = factory.newDocumentBuilder();
	        Document document = builder.parse(inputStream);
	        Element root = document.getDocumentElement();
	        
	        Element menuElement = document.getElementById("Menu");
	        NodeList tabNodeList = menuElement.getElementsByTagName("TabMenu");

结果还是获得空值:

getElementById for Menu also empty

8.再去试试:

	        NodeList nodeList = root.getChildNodes();

看看结果,是可以获得对应的子节点的:

[org.apache.harmony.xml.dom.TextImpl@211914f8, org.apache.harmony.xml.dom.ElementImpl@21191668, org.apache.harmony.xml.dom.TextImpl@21194f58, org.apache.harmony.xml.dom.ElementImpl@21194fb8, org.apache.harmony.xml.dom.TextImpl@21198c80, org.apache.harmony.xml.dom.ElementImpl@21198d48, org.apache.harmony.xml.dom.TextImpl@2119f038, org.apache.harmony.xml.dom.ElementImpl@2119f100, org.apache.harmony.xml.dom.TextImpl@211a16c0]

其中的4个ElementImpl才是我们所关心的节点。

9.也注意到:

xml – android getElementsByTagName returns empty list – Stack Overflow

中提到了,其遇到此问题的android的版本是3.0或3.1

所以去看看我此处的:

Samsung Galaxy Tab 3 GT-P5210

android版本是:4.2.2

结果也出现此问题。。。

 

【总结】

算了,截至目前:

虽然会遇到上述bug:

即:

NodeList nodeList = root.getElementsByTagName("Menu");

获得空列表。

但是此处,还是可以通过,直接使用

NodeList nodeList = root.getElementsByTagName("TabMenu");

的方式,去获得根节点其下的子节点的,暂时规避此问题,继续去写我的其他代码的。。。

转载请注明:在路上 » 【已解决】Android中用DOM方式解析xml时使用getElementsByTagName去获得节点结果为空

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

网友最新评论 (1)

  1. DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 之后加上一句: t_factory.setNamespaceAware(true); 就能调用: t_doc.getElementsByTagNameNS(XMLSignature.XMLNS,"Signature")
    yuchting8年前 (2016-03-02)回复
86 queries in 0.154 seconds, using 22.15MB memory