Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java: Общие вопросы > Ошибки парсинга XML файлов


Автор: zone51 30.12.2006, 03:37
Здравствуйте. У меня проблема. Есть код, разбирающий хмл файл
Код

import java.io.*;
import java.util.*;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.*;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

public class SAXHandler extends DefaultHandler
{

  //=======================================

  private String host;
  private String port;
  private String login;
  private String pwd;
  private String usDir;
  private String archDir;
  private String errDir;
  private String timeout;

  //=======================================
  
  private boolean isHost = false;
  private boolean isPort = false;
  private boolean isLogin = false;
  private boolean isPwd = false;
  private boolean isusDir = false;
  private boolean isArchDir = false;
  private boolean isErrDir = false;
  private boolean isTimeout = false;

  //=======================================
  
  public String getHost()
  {
    return host;
  }

  public String getPort()
  {
    return port;
  }

  public String getLogin()
  {
    return login;
  }

  public String getPwd()
  {
    return pwd;
  }

  public String getusDir()
  {
    return usDir;
  }

  public String getArchDir()
  {
    return archDir;
  }

  public String getErrDir()
  {
    return errDir;
  }

  public String getTimeout()
  {
    return timeout;
  }

  @Override
  public void startDocument() throws SAXException
  {
  
  }

  @Override
  public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException
  {
     isHost = "host".equals(qName);
     isPort = "port".equals(qName);
     isLogin = "login".equals(qName);
     isPwd = "pwd".equals(qName);
     isusDir = "us-dir".equals(qName);
     isArchDir = "arch-dir".equals(qName);
     isErrDir = "err-dir".equals(qName);
     isTimeout = "timeout".equals(qName);
  }

  @Override
  public void characters(char[] ch, int start, int length) throws SAXException
  {

    System.out.println("test="+String.valueOf(ch));

    if(isHost)host=String.valueOf(ch);
    else
    if(isPort)port=String.valueOf(ch);//Integer.parseInt(String.valueOf(ch));
    else
    if(isLogin)login=String.valueOf(ch);
    else
    if(isPwd)pwd=String.valueOf(ch);
    else
    if(isusDir)usDir=String.valueOf(ch);
    else
    if(isArchDir)archDir=String.valueOf(ch);
    else
    if(isErrDir)errDir=String.valueOf(ch);
    else
    if(isTimeout)timeout=String.valueOf(ch);//Integer.parseInt(String.valueOf(ch));
  }

  @Override
  public void endElement(String uri, String localName, String qName) throws SAXException
  {
     isHost = false;
     isPort = false;
     isLogin = false;
     isPwd = false;
     isusDir = false;
     isArchDir = false;
     isErrDir = false;
     isTimeout = false;
  }

  @Override
  public void endDocument() throws SAXException
  {
  }

  public static void main(String[] args) throws Exception
  {
    SAXParserFactory factory = SAXParserFactory.newInstance();
    SAXParser parser = factory.newSAXParser();

    SAXHandler handler = new SAXHandler();
    parser.parse(new File("apus.xml"), handler);

    System.out.println("host = " + handler.getHost());
    System.out.println("port = " + handler.getPort());
    System.out.println("login = " + handler.getLogin());
    System.out.println("password = " + handler.getPwd());
    System.out.println("usDir = " + handler.getusDir());
    System.out.println("ArchDir = " + handler.getArchDir());
    System.out.println("ErrDir = " + handler.getErrDir());
    System.out.println("Timeout = " + handler.getTimeout());

  }
}


Этот код не срабатывает, как будто файл просто не парсируется-в процедуры не передаютсяя нужные параметры. Подскажите. Спасибо.

Автор: y3u 30.12.2006, 12:30
что значит "не срабатывает"? опиши подробнее... и прицепи XMLник...
на вскидку 

Код

host=String.valueOf(ch);


это неправильно, там массив символов всего документа, думаешь зачем тебе там приходит в параметре  int start, int length ?

надо делать примерно так

Код

protected static String getNodeValue(char[] ch, int start, int length) {
        char [] buffer = new char[length];
        System.arraycopy(ch, start, buffer, 0, length);
        return String.valueOf(buffer);
    }

Автор: LSD 30.12.2006, 13:15
Цитата(y3u @  30.12.2006,  12:30 Найти цитируемый пост)
надо делать примерно так

Только промежуточный буфер не нужен.

Автор: zone51 30.12.2006, 13:32
y3u, 
Спасибо большое, все получилось smile

LSD, 
Цитата

Только промежуточный буфер не нужен.


А как это? Прямо в одну строку в ретурне и перегонять в строку массив?

Автор: LSD 30.12.2006, 13:36
Нет, просто вместо:
Код
char [] buffer = new char[length];
System.arraycopy(ch, start, buffer, 0, length);
return String.valueOf(buffer);

достаточно:
Код
return new String(ch, start, length);

Автор: sergejzr 30.12.2006, 13:37
zone51, пожалуйста пиши грамотно! smile

ПС:
Переименовал тему "Ошибки парсинга XML файлв, Необходимо разобрацца"->"Ошибки парсинга XML файлв, Необходимо разобраться"

Автор: y3u 30.12.2006, 13:37
...
век живи - век учись

там, вобщем-то, так же работает все smile

Автор: Hidrag 9.1.2007, 21:05
Встала задача парсинга XML, в факе почитал статью "Парсинг XML с помощью SAX парсера", все понятно и работает, там пример хмла такой:
Код

<?xml version="1.0" encoding="UTF-8"?>
<root>
  <user>User 1</user>
  <userParam>Param 1</userParam>

  <user>User 2</user>
  <userParam>Param 2</userParam>

  <user>User 3</user>
  <userParam>Param 3</userParam>
</root>

а вот как распарсить вот такой файл:
Код

<?xml version="1.0" encoding="windows-1251"?>
<root>
  <user>
     User 1
  </user>
  <userParam>
     Param 1
  </userParam>

  <user>
     User 2
  </user>
  <userParam>
     Param 2
  </userParam>

  <user>
      User 3
  </user>
  <userParam>
    Param 3
  </userParam>
</root>

вроде бы тот же самый файл, только тэги и данные на разных строчках и кодировка другая...
код из фака который получает стоку данных:
Код

  public void characters(char[] ch, int start, int length) throws SAXException
  {
    if(isUserTag)
      users.add(new String(ch, start, length));
  }

так вот при парсинге этого файла стринг получается состоит из 3-х (трех!!!) строк, то есть уже не строка а текст из трех строчек разделенных символом перевода строки в одном стринге (и как такое возможно? я думал стринг это одна строка), первая строка состоит из символа переноса строки, вторая строка из пробелов и той самой строки которая и нужна, и третья строка из пробелов от края до закрывающего тэга...

Пришло две мысли как это вылечить, либо распарсить эту строку и удалить в ней ненужные пробелы и символы переноса строк, второе решение это обработать сам хмльник и удалить в нем все символы переноса строк... но как мне кажется это "корявое" решение, не полдскажете как грамотнее распарсить такой файл?

.. и если все же удалять символы переноса строки как правильно сделать? Я сделал так:
Код

    private String stroka(char[] ch, int start, int length) {
        String s = new String(ch, start, length);
        String n = "";
        for (int i=0;i<s.length();i++) {
          if (!s.substring(i,i+1).equals("\n")) {
              n+=s.substring(i,i+1);
          }
        }
        return n;
    }


но он удалят эти символы как будто через строку... в одной удалит в другой пропустит, что я не так делаю?...

Автор: batigoal 10.1.2007, 11:11
Цитата(Hidrag @  9.1.2007,  22:05 Найти цитируемый пост)
(и как такое возможно? я думал стринг это одна строка)

Это одна строка, но содержащая в себе символы \n.

У DOM-парсера есть метод setIgnoringElementContentWhitespace(), но в SAX-парсинге я его не нашел...

Автор: y3u 10.1.2007, 11:32
ну, вобщем-то, в сакс модели дже отнормалайзить дерево не получится... поэтому, имхо, вполне себе нормальный выход, зачитывать строку, а потом просто дергать у нее метод trim(), который обрежет все вайтспейсы со строки, в том числе и переносы...

Автор: Hidrag 10.1.2007, 20:18
Решил седня проблему так: использовал вместо сакса дом. Трим к строке использовать нельзя, там может храниться фраза а не одно слово, а чтобы убрать все лишнее использовал регулярное выражение, вот такое:

Код

s=s.replaceAll("^\\s*","").replaceAll("\\s*$",""));

которое обрубает все лишнее в начале и конце строки.
Где s полученная строка данных.

Автор: y3u 10.1.2007, 22:45
trim() обрезает все в начале и в конце строки целиком... при чем тут фраза

Автор: Hidrag 10.1.2007, 23:07
y3u, Проверил и правда... а я думал он только пробелы удаляет...

Автор: tigerkvv 14.12.2010, 17:38
Продолжение. Как парсить вот такой файл:
Код

<?xml version="1.0" encoding="windows-1251"?>
<root>
  <user>
     User 1
  </user>
  <userParam>
     Param 1.1
     Param 1.2
  </userParam>
  <user>
     User 2
  </user>
  <userParam>
     Param 2.1
     Param 2.2
  </userParam>
</root>

вышеописанный метод 
Код

return new String(ch, start, length);

от <userParam> оставляет только "\nParam 1.2\n" и "\nParam 2.2\n"
куда пропадают "\nParam 1.1\n" и "\nParam 2.1\n" ?

Автор: LSD 14.12.2010, 18:41
Цитата(tigerkvv @  14.12.2010,  18:38 Найти цитируемый пост)
Как парсить вот такой файл:

В FAQ есть статья на тему как правильно парсить XML с помощью SAX.

Автор: tigerkvv 15.12.2010, 18:26
Спасибо за ответ. С той статьей я знакомился и тот код отлично работает для файла из примера, но для моего файла тод код выдает только последнюю строчку из многострочного параметра. Возможно есть что-то в комментариях, но мне их не видно (я зарегистрирован), видно только даты комментариев.

Автор: LSD 16.12.2010, 14:58
Там в FAQ не совсем корректный код, более правильно так:
Код

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import java.io.File;
import java.util.ArrayList;

public class SAXHandler extends DefaultHandler {
    private StringBuilder buffer = new StringBuilder();
    private ArrayList<String> users;
    private boolean isUserTag = false;

    public String[] getUsers() {
        return users.toArray(new String[users.size()]);
    }

    @Override
    public void startDocument() throws SAXException {
        users = new ArrayList<String>();
    }

    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        isUserTag = "user".equals(qName);
        if (isUserTag) {
            buffer.setLength(0);
        }
    }

    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
        if (isUserTag) {
            buffer.append(ch, start, length);
        }
    }

    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {
        if (isUserTag) {
            users.add(buffer.toString());
            isUserTag = false;
        }
    }

    @Override
    public void endDocument() throws SAXException {
    }

    public static void main(String[] args) throws Exception {
        SAXParserFactory factory = SAXParserFactory.newInstance();
        SAXParser parser = factory.newSAXParser();

        SAXHandler handler = new SAXHandler();
        parser.parse(new File("some.xml"), handler);

        for (String user : handler.getUsers())
            System.out.println("user = " + user);
    }
}

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)