从getChildNodes返回的空/空节点

时间:2014-07-02 14:27:51

标签: java xml nodelist

我正在尝试解析以下XML:

<?xml version="1.0" encoding="UTF-8"?>
<docusign-cfg>
    <tagConfig>
        <tags>
            <approve>approve</approve>
            <checkbox>checkbox</checkbox>
            <company>company</company>
            <date>date</date>
            <decline>decline</decline>
            <email>email</email>
            <emailAddress>emailAddress</emailAddress>
            <envelopeID>envelopeID</envelopeID>
            <firstName>firstName</firstName>
            <lastName>lastName</lastName>
            <number>number</number>
            <ssn>ssn</ssn>
            <zip>zip</zip>
            <signHere>signHere</signHere>
            <checkbox>checkbox</checkbox>
            <initialHere>initialHere</initialHere>
            <dateSigned>dateSigned</dateSigned>
            <fullName>fullName</fullName>
        </tags>
    </tagConfig>
</docusign-cfg>

我想阅读<tags>标记中每个标记的名称或内容。我可以使用以下代码执行此操作:

public String[] getAvailableTags() throws Exception
{

    String path = "/docusign-cfg/tagConfig/tags";
    XPathFactory f = XPathFactory.newInstance();
    XPath x = f.newXPath();
    Object result = null;
    try 
    {
        XPathExpression expr = x.compile(path);
        result = expr.evaluate(doc, XPathConstants.NODE);
    } 
    catch (XPathExpressionException e) 
    {
        throw new Exception("An error ocurred while trying to retrieve the tags");
    }

    Node node = (Node) result;
    NodeList childNodes = node.getChildNodes();
    String[] tags = new String[childNodes.getLength()];
    System.out.println(tags.length);
    for(int i = 0; i < tags.length; i++)
    {
        String content = childNodes.item(i).getNodeName().trim().replaceAll("\\s", "");

        if(childNodes.item(i).getNodeType() == Node.ELEMENT_NODE &&
                childNodes.item(i).getNodeName() != null)
        {
            tags[i] = content;
        }
    }

    return tags;
}

经过一些搜索后,我发现以这种方式解析它会导致它读取节点/标记之间的空白,导致这些空格被视为子节点。在这种情况下,空格被视为<tags>的子项。

我的输出:

37
null
approve
null
checkbox
null
company
null
date
null
decline
null
email
null
emailAddress
null
envelopeID
null
firstName
null
lastName
null
number
null
ssn
null
zip
null
signHere
null
checkbox
null
initialHere
null
dateSigned
null
fullName
null

37是它在<tags>中找到的节点数 低于37的所有内容都是tag数组的内容。

尽管我检查了null,但是如何将这些null元素添加到tag数组?

2 个答案:

答案 0 :(得分:0)

标签数组的内容默认为null。

因此,不是元素如何变为null的情况,而是将其保留为null。

要向自己证明这一点,请添加以下其他块:

   if(childNodes.item(i).getNodeType() == Node.ELEMENT_NODE &&
            childNodes.item(i).getNodeName() != null)
    {
        tags[i] = content;
    } else {
        tags[i] = "Foo Bar";
    } 

你现在应该看到&#39; Foo Bar&#39;而不是null。

这里更好的解决方案是使用ArrayList,并将标签附加到它而不是使用数组。然后你不需要跟踪索引,因此这类bug的可能性就会降低。

答案 1 :(得分:0)

我认为这是因为标记的索引。 if检查也会跳过索引。因此,即使没有插入值,也会导致null。为标记数组使用单独的索引

int j = 0;
for(int i = 0; i < tags.length; i++)
{
    String content = childNodes.item(i).getNodeName().trim().replaceAll("\\s", "");

    if(childNodes.item(i).getNodeType() == Node.ELEMENT_NODE &&
        childNodes.item(i).getNodeName() != null)
    {
        tags[j++] = content;
    }
}

由于您省略了某些子节点,因此创建整个子节点长度的数组可能会导致内存浪费。您可以改用List。如果您特别关注String数组,您可以稍后将其转换为数组。

public String[] getAvailableTags() throws Exception
{
    String path = "/docusign-cfg/tagConfig/tags";
    XPathFactory f = XPathFactory.newInstance();
    XPath x = f.newXPath();
    Object result = null;
    try 
    {
        XPathExpression expr = x.compile(path);
        result = expr.evaluate(doc, XPathConstants.NODE);
    } 
    catch (XPathExpressionException e) 
    {
        throw new Exception("An error ocurred while trying to retrieve the tags");
    }

    Node node = (Node) result;
    NodeList childNodes = node.getChildNodes();
    List<String> tags = new ArrayList<String>();
    for(int i = 0; i < tags.length; i++)
    {
        String content = childNodes.item(i).getNodeName().trim().replaceAll("\\s", "");

        if(childNodes.item(i).getNodeType() == Node.ELEMENT_NODE &&
            childNodes.item(i).getNodeName() != null)
        {
            tags.add(content);
        }
    }

    String[] tagsArray = tags.toArray(new String[tags.size()]);
    return tagsArray;
}