Почему XML Dom в Java сообщает о дополнительных узлах?

У меня есть простое XML-представление таблицы ниже. Когда я прохожу только верхний уровень с кодом (приведенным ниже). Я получаю 5 узлов, хотя в приведенном примере их всего 2 (theader и tbody). Может кто-нибудь объяснить, почему?

package testparser;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.Vector;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class TestParser {
    private static final int FILE_small = 1;
    private static final int FILE_medium = 2;
    private static final int FILE_large = 3;
    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        doDomTest(1);

    }
    private static void doDomTest(int sizeId) {
        String filename = getFileNameFromId(sizeId);

        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        try {
            DocumentBuilder db = dbf.newDocumentBuilder();
            FileInputStream fis = new FileInputStream(filename);
            Document doc = db.parse(fis);

            Element topElement = doc.getDocumentElement();

            NodeList nl = topElement.getChildNodes();

            int ilen = nl.getLength();
            print("Top Element count " + ilen);
            for (int i=0;i<ilen;i++){
                Node node = nl.item(i);
                if (node.getNodeType()==Node.TEXT_NODE) {
                    print(i + ". Name:" + node.getNodeName() + "= " + node.getNodeValue() + ". type " + node.getNodeType());
                } else {
                    print(i + ". Name:" + node.getNodeName() + ", type " + node.getNodeType());
                }
            }


        } catch (Exception e) {
            e.printStackTrace();
        }

    }


    private static String getFileNameFromId(int sizeId) {
        String sReturn = "";
        switch (sizeId) {
        case FILE_small:
            sReturn = "D:/temp/testdata_ok.xml";
            break;
        case FILE_medium:
            sReturn = "D:/temp/testdata_ok.xml";
            break;
        case FILE_large:
            sReturn = "D:/temp/testdata_ok.xml";
            break;
        }
        return sReturn;
    }

    private static void print(String sValue) {
        System.out.println(sValue);
    }  
}

ИСПЫТАТЕЛЬНЫЕ ДАННЫЕ

<?xml version="1.0" encoding="utf-8"?>
<table>
    <theader>
        <tr>
            <th>Title Col1</th>
            <th>Title Col2</th>
            <th>Title Col3</th>
            <th>Title Col4</th>
        </tr>
    </theader>
    <tbody>
        <tr>
            <td>data:R1C1</td>
            <td>data:R1C2</td>
            <td>data:R1C3</td>
            <td>data:R1C4</td>
        </tr>
        <tr>
            <td>data:R2C1</td>
            <td>data:R2C2</td>
            <td>data:R2C3</td>
            <td>data:R2C4</td>
        </tr>
        <tr>
            <td>data:R3C1</td>
            <td>data:R3C2</td>
            <td>data:R3C3</td>
            <td>data:R3C4</td>
        </tr>
        <tr>
            <td>data:R4C1</td>
            <td>data:R4C2</td>
            <td>data:R4C3</td>
            <td>data:R4C4</td>
        </tr>
        <tr>
            <td>data:R5C1</td>
            <td>data:R5C2</td>
            <td>data:R5C3</td>
            <td>data:R5C4</td>
        </tr>
    </tbody>
</table>

Консольный вывод

Top Element count 5
0. Name:#text= 
    . type 3
1. Name:theader, type 1
2. Name:#text= 
    . type 3
3. Name:tbody, type 1
4. Name:#text= 
. type 3

Обратите внимание, что в выводе отображаются theader и tbody (строки 1 и 3), но у меня также есть элементы 0, 2 и 4. Зачем лишние узлы? Я ожидал, что только строки со списком 0 и 1 для theader и tbody соответственно.

«Тип 1»/«тип 3» представляет собой значение метода «getNodeType()», также напечатанное в выводе. Я обнаружил, что getNodeType() означает здесь.

Я использую JDK 1.6.0u24.


person angryITguy    schedule 06.04.2011    source источник


Ответы (2)


Три дополнительных узла — это текстовые узлы, представляющие пробелы:

  • между <table> и <theader>
  • между </theader> и <tbody> и
  • между </tbody> и </table>.

Я не уверен в этом, но я думаю, что вы могли бы удалить узлы, позвонив

    dbf.setIgnoringElementContentWhitespace(true);

Прочтите документ Java, обращая внимание на бит, который говорит, что синтаксический анализатор должен быть в режиме проверки...

person Stephen C    schedule 06.04.2011
comment
Я собирался спросить, как игнорировать пробелы, определив общий dtd или если есть какая-то настройка. Читая документ, на который вы ссылаетесь, мне нужно также перевести синтаксический анализатор в режим проверки, чтобы использовать этот параметр? - person angryITguy; 06.04.2011
comment
@Степехен. Быстрый тест выявил некоторые проблемы. Если я активирую setValidating(true), это вызывает исключение, потому что (по понятным причинам) в списке нет схемы. Кажется, что игнорирование пробелов не сработает без setValidating(true).. аааааа!!! - person angryITguy; 06.04.2011
comment
Нашел это как ответ на проблему с пробелами stackoverflow.com/questions/229310/ - person angryITguy; 06.04.2011
comment
@guilio - вот почему я предупредил вас обратить внимание на javadoc. :-) Основная проблема заключается в том, что синтаксический анализатор XML не может сказать, можно ли игнорировать пробелы (или нет), если только нет схемы или DTD, чтобы сообщить ему, что ожидается. - person Stephen C; 07.04.2011

Как видно из вашего вывода, это пробелы между элементами table и theader/tbody. Без DTD или схемы синтаксический анализатор не знает, что эти пробелы можно игнорировать. Вам придется пропустить эти узлы в коде парсера.

person Jörn Horstmann    schedule 06.04.2011