Java:解析XML文件时出现问题

时间:2011-04-06 15:21:32

标签: java

我有以下XML,我正在尝试打印某些节点的值。例如,使用以下代码我想打印

 NodeList list = doc.getElementsByTagName("photo");
 element = (Element)list.item(0);
 list = element.getChildNodes();
 System.out.println(list.item(0).getNodeName());
 System.out.println(list.item(0).getNodeValue());

我得到了

null
#text

而不是“title”和“bigfish live 200812”

我做错了什么? 感谢

<?xml version="1.0" encoding="utf-8" ?> 
<rsp stat="ok"> 
<photo id="2882550369" secret="21054282c8" server="3106" farm="4" dateuploaded="1222202793" isfavorite="0" license="0" safety_level="0" rotation="0" views="5" media="photo"> 
    <owner nsid="64878451@N00" username="fishthemusic" realname="masayoshi yamamiya" location="kawasaki, japan" iconserver="4" iconfarm="1" /> 
    <title>bigfish live 200812</title> 
    <description>photo by Kazuhiro Nakamura</description> 
    <visibility ispublic="1" isfriend="0" isfamily="0" /> 
    <dates posted="1222202793" taken="2008-09-24 05:46:33" takengranularity="0" lastupdate="1222998937" /> 
    <editability cancomment="1" canaddmeta="0" /> 
    <publiceditability cancomment="1" canaddmeta="0" /> 
    <usage candownload="1" canblog="1" canprint="0" canshare="1" /> 
    <comments>0</comments> 
    <notes /> 
    <tags> 
        <tag id="314160-2882550369-80673" author="64878451@N00" raw="bigfish" machine_tag="0">bigfish</tag> 
        <tag id="314160-2882550369-5558" author="64878451@N00" raw="live" machine_tag="0">live</tag> 
        <tag id="314160-2882550369-29726586" author="64878451@N00" raw="upcoming:event=1167424" machine_tag="1">upcoming:event=1167424</tag> 
    </tags> 
    <urls> 
        <url type="photopage">http://www.flickr.com/photos/fishthemusic/2882550369/</url> 
    </urls> 
</photo> 
</rsp>

3 个答案:

答案 0 :(得分:3)

您的photo元素中有文字节点,在下面的示例中标记为XXXX。你得到这个文本节点。请注意,可能存在多个相邻的文本节点。您需要找到具有Element类型的第一个节点才能获得owner元素。

<photo ...>XXXX 
XXXX<owner nsid="64878451@N00" ... /> 

请改为尝试:

NodeList list = doc.getElementsByTagName("photo");
element = (Element)list.item(0);
list = element.getChildNodes();

int ix = 0;
while (ix < list.getLength() && list.item(ix).getNodeType() != Node.ELEMENT_NODE) {
  ix++;
}

// now ix points to your first element node (if there was one)

System.out.println(list.item(ix).getNodeName());
System.out.println(list.item(ix).getNodeValue());

顺便说一下,元素的“nodeValue”是null,所以你应该看到

owner
null

作为输出。有关详细信息,另请参阅http://download.oracle.com/javase/6/docs/api/org/w3c/dom/Node.html。 (它还显示#text是文本节点的nodeName,正是你得到的。)

答案 1 :(得分:0)

因为当您致电element.getChildNodes()时,您将获得该元素的所有子项,其中包含idsecret等属性。所以list.item(0)是一个属性,这就是为什么你没有得到你期望的结果。

getNodeName()返回null,因为属性没有节点名称
getNodeValue()返回#text,因为属性的值是文本节点,而文本节点又保存该属性的字符串值。

此外,请不要重新定义相同的变量(例如list)以重新使用完全不同的内容。这真的很糟糕。

答案 2 :(得分:-1)

使用JAXB代替SAX / DOM将使这种火箭科学变得更加容易。有关说明,请参阅this article

首先,编写等效的XSD架构(可以省略不需要的节点);这是一个好的开始:

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <xsd:element name="photo">
        <xsd:complexType>
            <xsd:sequence>
                <xsd:element name="owner" type="owner" />
                <xsd:element name="title" type="xsd:string" />
            </xsd:sequence>
            <xsd:attribute name="id" type="xsd:int" />
            <xsd:attribute name="secret" type="xsd:string" />
        </xsd:complexType>
    </xsd:element>

    <xsd:complexType name="owner">
        <xsd:attribute name="nsid" type="xsd:string" />
    </xsd:complexType>
</xsd:schema>

其次,使用此maven插件从此生成类:http://mojo.codehaus.org/jaxb2-maven-plugin/usage.html

然后,编写一些代码(并将JAXB maven dependency添加到项目中):

public class JaxbTest {
    @Test
    public void should_parse_recipe() throws JAXBException {
        URL xmlUrl = Resources.getResource("file.xml");
        Photo recipe = parse(xmlUrl, Photo.class);
        assertEquals(Integer.valueOf(15), recipe.getCooking().getDuration());
    }

    private <T> T parse(URL url, Class<T> clazz) throws JAXBException {
        Unmarshaller unmarsh = JAXBContext.newInstance(clazz).createUnmarshaller();
        return clazz.cast(unmarsh.unmarshal(url));
    }
}

PS。 Resources.getResource来自番石榴;使用Thread.currentThread()。getContextClassLoader()。getSystemResource(“file.xml”)代替工作