Пустые / пустые узлы возвращены из getChildNodes
Я пытаюсь разобрать следующий 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
массив.
Как эти нулевые элементы добавляются в tag
массив несмотря на мою проверку на ноль?
2 ответа
Я думаю, что это из-за индексации тега. Проверка if также пропускает индекс. Таким образом, даже если значение не вставляется, оно приведет к нулю. Используйте отдельный индекс для массива тегов
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;
}
}
Так как вы опускаете некоторые дочерние узлы, создание массива всей длины дочерних узлов может привести к потере памяти. Вы можете использовать список вместо. Если вы неравнодушны к массиву 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;
}
Содержимое массива тегов по умолчанию равно нулю.
Таким образом, дело не в том, как элемент становится нулевым, а в том, чтобы оставить его равным нулю.
Чтобы доказать это себе, добавьте следующий блок else, например так:
if(childNodes.item(i).getNodeType() == Node.ELEMENT_NODE &&
childNodes.item(i).getNodeName() != null)
{
tags[i] = content;
} else {
tags[i] = "Foo Bar";
}
Теперь вы должны увидеть 'Foo Bar' вместо null.
Лучшее решение здесь - использовать ArrayList и добавлять к нему теги вместо использования массива. Тогда вам не нужно отслеживать индексы и, следовательно, меньше шансов на этот тип ошибки.