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


Автор: Alexandr87 10.5.2006, 14:02

Есть некая xml структура, упрощенно выглядящая так.
<request arg='qwerty'>
<action arg1='power' arg2='4'>
<doc dynArg1='power' dynArg2='clower' />
</action>
</request>

Теги <request> и <action> - имеют фиксированное число аргументов.
Вид (аргументы, внутренние элементы) тега <doc> определяется на основе значения агрументов тега <action>.

Предполагалось разбирать данную структуру - двумя парсерами (внутренним и внешним). Внешний парсит нужные агрументы тегов <request> и <action> и на их основе динамически подгружает нужный парсер (внутренний) для анализа внутренней структуры.


Парсится InputStream.
При создании внешнего Handler а, я передаю ему через конструктор ссылку на этот объект, так, чтобы он мог вызвать внутренний парсер, передав ему данную ссылку для разбора.

Но в момент начала работы внутреннего парсера вылетает ошибка 
java.io.IOException: Bad file descriptor

Не могу понять, то ли это SAXParser парсит сразу все, а не постепенно, то ли еще чего.

примерный код
Код

public class Power {
    public static void main(String args[]) throws Exception {

        FileInputStream  fis = new FileInputStream("/home/alexandr/xml.xml");
        SAXParserFactory sfact = SAXParserFactory.newInstance();
        SAXParser saxParser = sfact.newSAXParser();
        MyXMLParser mxp = new MyXMLParser(fis);
        saxParser.parse(fis, mxp);
        fis.close();
    }
}

class MyXMLParser extends DefaultHandler {

    FileInputStream is;
    
    public MyXMLParser(FileInputStream is) {
        this.is=is;
    }
    
    public void startElement(String arg0, String arg1, String arg2,
            Attributes arg3) throws SAXException {
            .................
            SAXParserFactory spf = SAXParserFactory.newInstance();
            SAXParser spars;
            spars = spf.newSAXParser();
            MyInnerXMLParser minnerparser = new MyInnerXMLParser();
            spars.parse(is, minnerparser);
        }
    }
}

class MyInnerXMLParser extends DefaultHandler {

    public void startElement(String arg0, String arg1, String arg2,
            Attributes arg3) throws SAXException {
        if (arg2.equals("doc") && arg3!=null) {
            System.out.println("Name: " + arg3.getValue("name"));
            System.out.println("Text: " + arg3.getValue("text"));
        }
    }
}



ошибка
Цитата

java.io.IOException: Bad file descriptor
    at java.io.FileInputStream.readBytes(Native Method)
    at java.io.FileInputStream.read(FileInputStream.java:194)
    at java.io.FilterInputStream.read(FilterInputStream.java:111)
    at java.io.PushbackInputStream.read(PushbackInputStream.java:161)
    at java.io.FilterInputStream.read(FilterInputStream.java:90)
    at org.apache.crimson.parser.XmlReader.<init>(XmlReader.java:248)
    at org.apache.crimson.parser.XmlReader.createReader(XmlReader.java:125)
    at org.apache.crimson.parser.InputEntity.init(InputEntity.java:215)
    at org.apache.crimson.parser.Parser2.parseInternal(Parser2.java:638)
    at org.apache.crimson.parser.Parser2.parse(Parser2.java:337)
    at org.apache.crimson.parser.XMLReaderImpl.parse(XMLReaderImpl.java:448)
    at javax.xml.parsers.SAXParser.parse(SAXParser.java:345)
    at javax.xml.parsers.SAXParser.parse(SAXParser.java:143)
    at MyXMLParser.startElement(Power.java:57)
    at org.apache.crimson.parser.Parser2.maybeElement(Parser2.java:1674)
    at org.apache.crimson.parser.Parser2.content(Parser2.java:1963)
    at org.apache.crimson.parser.Parser2.maybeElement(Parser2.java:1691)
    at org.apache.crimson.parser.Parser2.parseInternal(Parser2.java:667)
    at org.apache.crimson.parser.Parser2.parse(Parser2.java:337)
    at org.apache.crimson.parser.XMLReaderImpl.parse(XMLReaderImpl.java:448)
    at javax.xml.parsers.SAXParser.parse(SAXParser.java:345)
    at javax.xml.parsers.SAXParser.parse(SAXParser.java:143)
    at Power.main(Power.java:17)


Заранее благодарен. 

Автор: kashka 10.5.2006, 14:59
XML файл неправильный. Попробуй ' на " заменить. И проверь dtd файл, может там что не подходит. 

Автор: Alexandr87 11.5.2006, 04:33
про ddt в моем посте нет ни слова. Он не используется.

Какие могут быть альтернативные пути решения задачи. Или она не понятна. 

Автор: tux 11.5.2006, 04:55
Возможно возникновение такого исключения если у XML нет заголовка с указанием кодировки (тогда вероятно используется iso-8859-1), но при этом в документе имеются кириллические символы. Если заголовок поставить (если его нет, конечно)? 
Код

<?xml version="1.0" encoding="UTF-8"?>
 

Автор: Alexandr87 11.5.2006, 17:21
итак xml.xml
Цитата

<?xml version="1.0" encoding="UTF-8"?>
<request>
<action act="new" doc_type="1" doc_nom="2">
<doc name="caption" text="what a f" />
</action>
</request>


А это точный код, в котором возникает вышеописанная ситуация.
Код

import java.io.FileInputStream;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public class Power {
    public static void main(String args[]) throws Exception {

        FileInputStream  fis = new FileInputStream("/home/alexandr/xml.xml");
        MyXMLParser mxp = new MyXMLParser(fis);
        SAXParserFactory sfact = SAXParserFactory.newInstance();
        SAXParser saxParser = sfact.newSAXParser();
        saxParser.parse(fis, mxp);
        fis.close();
    }
}

class MyXMLParser extends DefaultHandler {

    FileInputStream is;
    
    public MyXMLParser(FileInputStream is) {
        this.is=is;
    }
    
    public void startElement(String arg0, String arg1, String arg2,
            Attributes arg3) throws SAXException {
        if (arg2.equals("request")) {
            //......................
        } else if (arg2.equals("action")) {
            System.out.println("Action tag");
            System.out.println("act: " + arg3.getValue("act"));
            System.out.println("doc_nom: " +arg3.getValue("doc_nom"));
            System.out.println("doc_type: " + arg3.getValue("doc_type"));
            SAXParserFactory spf = SAXParserFactory.newInstance();
            SAXParser spars;
            try {
                spars = spf.newSAXParser();
            } catch (Exception e) {
                e.printStackTrace();
                return;
            }
            MyInnerXMLParser mInnerParser = new MyInnerXMLParser();
            try {
                spars.parse(is, mInnerParser);
            } catch (Exception e) {
                e.printStackTrace();
                return;
            }
            
        }
    }
}

class MyInnerXMLParser extends DefaultHandler {


    public void endElement(String arg0, String arg1, String arg2)
            throws SAXException {
    }

    public void startElement(String arg0, String arg1, String arg2,
            Attributes arg3) throws SAXException {
        if (arg2.equals("doc") && arg3!=null) {
            System.out.println("doc tag <from inner>");
            System.out.println("Name: " + arg3.getValue("name"));
            System.out.println("Text: " + arg3.getValue("text"));
        }
    }
}

 

Автор: LSD 11.5.2006, 22:30
Дык чтож ты хочешь! Ты же в DefaultHandler в обработчике тега, начинаешь парсить этот же файл из того же самого FileInputStream! Естественно он перемещает позицию в файле на конец файла, вот ты и получаешь ошибку. 

Автор: Alexandr87 12.5.2006, 04:43
Я просто думал - что он парсит файл последовательно - не все сразу, и останавливается на теге - на котором вызывает очередной метод DefaultHandler.

А как тогда можно попробовать? 

Автор: LSD 12.5.2006, 19:33
Никто не может гарантировать, что текущая позиция в InputStream будет соответсвовать тегу, скорее всего нет. Почти наверняка они используют буферизацию. Тем более процесс парсинга SAX парсером не остановить, пока он не дойдет до конца.

А зачем это вообще нужно? 

Автор: Alexandr87 13.5.2006, 14:40
внутренняя часть, динамическая и парсится разными наследниками DefaultHandler, которые при обработке вытягивают нужные данные и записывают их куда следуют, но заранее не известен полный список возможных внутренних (динамических) структур, и в зависимости от значений полученных во внешней структуре, выбирается необходимый класс-парсер, который далее и обрабатывает данный кусок и делает все что на него возложили.
Или пояснить более детально?
Есть ли альтернативные способы. 

Автор: LSD 14.5.2006, 01:05
Цитата(Alexandr87 @  13.5.2006,  15:40 Найти цитируемый пост)
Есть ли альтернативные способы.

Использовать один DefaultHandler, а он в зависимости от полученных данных пусть вызывает соответсвующий обработчкик. Например это можно реализовать так: у умолчального обработчика есть Map в которой записано на каком теге какого обработчика надо вызвать, и есть поле текущий обработчик. Когда приходит тег и для него есть обработчик, то он делается текущим обработчиком. И далее когда происходят SAX события, вызывается именно текущий обработчик. После того как текущий обработчик завершил работу, он разрегистрируется в умолчальном обработчике и тот снова начинает обрабатывать события самостоятельно.

P.S. А еще можно сделать не одного текущего обработчика, а стек. 

Автор: Alexandr87 14.5.2006, 05:44
Спасибо LSD. Что то мне кажется, что так и придется делать.
Хотя на мой взгляд, было бы удобнее если можно было запустить еще один парсер.
  

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