разбор XML-файла с ошибкой DOM [дубликат]

Этот вопрос довольно старый, так как современное обновление. С наступлением ES2015 есть альтернативы для получения требуемых данных. В настоящее время существует функция, называемая деструктурированием объекта для доступа к вложенным объектам.

const data = {
  code: 42,
  items: [{
    id: 1,
    name: 'foo'
  }, {
    id: 2,
    name: 'bar'
  }]
};

const {
  items: [, {
    name: secondName
  }]
} = data;

console.log(secondName);

В приведенном выше примере создается переменная, называемая secondName из name из массива с именем items, одиночный , говорит пропустить первый объект в массиве.

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

Это очень краткое введение в ваш конкретный вариант использования, деструктурирование может быть необычным синтаксисом, чтобы привыкнуть к нему сначала. Я бы порекомендовал прочитать документацию по присваиванию демаркации Mozilla , чтобы узнать больше.

18
задан Johannes Ernst 19 March 2016 в 01:19
поделиться

5 ответов

Для этой цели я бы использовал библиотеку Jsoup. Я проверил следующее ниже, и он работает. Я не знаю, поможет ли это. Он может быть расположен здесь: http://jsoup.org/download

public static void main(String args[]){


    String html = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><foo>" + 
                  "<bar>Some&nbsp;text &mdash; invalid!</bar></foo>";
    Document doc = Jsoup.parse(html, "", Parser.xmlParser());

    for (Element e : doc.select("bar")) {
        System.out.println(e);
    }   


}

Результат:

<bar>
 Some&nbsp;text — invalid!
</bar>

Загрузка из файла может быть найдено здесь:

http://jsoup.org/cookbook/input/load-document-from-file

7
ответ дан applecrusher 26 August 2018 в 03:42
поделиться

Проблема - 1: Мне нужно разобрать кучу XML-файлов на Java, которые иногда и недействительно содержат HTML-объекты, такие как &mdash;

. XML имеет только пять предопределенных объектов . &mdash;, &nbsp; не входит в их число. Он работает только при использовании в простом HTML или в устаревшем JSP. Таким образом, SAX не поможет. Это можно сделать, используя StaX, который имеет API-интерфейс с высоким уровнем итератора. [Собрано из этой ссылки )

Проблема - 2: Я обнаружил, что могу переопределить resolveEntity в org.xml.sax.helpers.DefaultHandler, но как использовать это с API более высокого уровня?

Streaming API для XML, называемый StaX, является API для reading and writing XML Documents.

StaX - это Pull-Parsing модель. Приложение может взять на себя управление анализом XML-документов, потянув (принимая) события от анализатора.

Ядро StaX API относится к two categories, и они перечислены ниже. Они

  • API на основе курсора: это low-level API. API на основе курсора позволяет приложению обрабатывать XML как поток токенов aka events
  • API на основе Iterator: API-интерфейс, основанный на итераторе higher-level, позволяет приложению обрабатывать XML как ряд объектов событий, каждый из которых связывает фрагмент структуры XML с приложением.

STaX API has support for the notion of not replacing character entity references, с помощью свойства IS_REPLACING_ENTITY_REFERENCES :

Требуется, чтобы синтаксический анализатор заменил ссылки на внутренние сущности ссылкой на их заменяющий текст и отчет их как символы

Это можно установить в XmlInputFactory, который затем, в свою очередь, используется для построения XmlEventReader или XmlStreamReader.

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

Вы можете попробовать. Надеюсь, он решит вашу проблему. Для вашего случая,

Main.java

import java.io.FileInputStream;
import java.io.FileNotFoundException;

import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.EntityReference;
import javax.xml.stream.events.XMLEvent;

public class Main {

    public static void main(String[] args) {
        XMLInputFactory inputFactory = XMLInputFactory.newInstance();
        inputFactory.setProperty(
                XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, false);
        XMLEventReader reader;
        try {
            reader = inputFactory
                    .createXMLEventReader(new FileInputStream("F://test.xml"));
            while (reader.hasNext()) {
                XMLEvent event = reader.nextEvent();
                if (event.isEntityReference()) {
                    EntityReference ref = (EntityReference) event;
                    System.out.println("Entity Reference: " + ref.getName());
                }
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (XMLStreamException e) {
            e.printStackTrace();
        }
    }
}

test.xml:

<?xml version="1.0" encoding="UTF-8"?>
<foo>
    <bar>Some&nbsp;text &mdash; invalid!</bar>
</foo>

Выход:

Ссылка на объект: nbsp

Ссылка на объект: mdash

Кредит отправляется на @skaffman.

Ссылки по теме:

  1. http://www.journaldev.com/1191/how-to-read-xml-file-in-java-using-java-stax-api
  2. http://www.journaldev.com/1226/java-stax-cursor-based-api-read-xml-example
  3. http: // www. vogella.com/tutorials/JavaXML/article.html
  4. Существует ли Java XML API, который может анализировать документ без разрешения объектов символов?

UPDATE:

Проблема - 3: Есть ли способ использовать StaX для «фильтрации» сущностей (например, заменяя их чем-то другим) и все еще обрабатывать документ в конце процесса?

Чтобы создать новый документ с использованием API StAX, необходимо создать XMLStreamWriter, который предоставляет методы для создания XML-открывания и закрытия теги, атрибуты и содержание символов.

Для документа существует 5 методов XMLStreamWriter.

  1. xmlsw.writeStartDocument(); - инициализирует пустой документ, к которому можно добавить элементы
  2. xmlsw.writeStartElement(String s) - создает новый элемент с именем s
  3. xmlsw.writeAttribute(String name, String value) - добавляет имя атрибута с соответствующим значением последнему элементу, создаваемому вызовом writeStartElement. Можно добавлять атрибуты до тех пор, пока не будет выполнен вызов writeElementStart, writeCharacters или writeEndElement.
  4. xmlsw.writeEndElement - закрыть последний начатый элемент
  5. xmlsw.writeCharacters(String s) - создает новый текстовый узел с содержимым s в качестве содержимого последнего начатого элемента.

Пример с примером прилагается:

StAXExpand.java

import  java.io.BufferedReader;
import  java.io.FileReader;
import  java.io.IOException;

import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;

import java.util.Arrays;

public class StAXExpand {   
    static XMLStreamWriter xmlsw = null;
    public static void main(String[] argv) {
        try {
            xmlsw = XMLOutputFactory.newInstance()
                          .createXMLStreamWriter(System.out);
            CompactTokenizer tok = new CompactTokenizer(
                          new FileReader(argv[0]));

            String rootName = "dummyRoot";
            // ignore everything preceding the word before the first "["
            while(!tok.nextToken().equals("[")){
                rootName=tok.getToken();
            }
            // start creating new document
            xmlsw.writeStartDocument();
            ignorableSpacing(0);
            xmlsw.writeStartElement(rootName);
            expand(tok,3);
            ignorableSpacing(0);
            xmlsw.writeEndDocument();

            xmlsw.flush();
            xmlsw.close();
        } catch (XMLStreamException e){
            System.out.println(e.getMessage());
        } catch (IOException ex) {
            System.out.println("IOException"+ex);
            ex.printStackTrace();
        }
    }

    public static void expand(CompactTokenizer tok, int indent) 
        throws IOException,XMLStreamException {
        tok.skip("["); 
        while(tok.getToken().equals("@")) {// add attributes
            String attName = tok.nextToken();
            tok.nextToken();
            xmlsw.writeAttribute(attName,tok.skip("["));
            tok.nextToken();
            tok.skip("]");
        }
        boolean lastWasElement=true; // for controlling the output of newlines 
        while(!tok.getToken().equals("]")){ // process content 
            String s = tok.getToken().trim();
            tok.nextToken();
            if(tok.getToken().equals("[")){
                if(lastWasElement)ignorableSpacing(indent);
                xmlsw.writeStartElement(s);
                expand(tok,indent+3);
                lastWasElement=true;
            } else {
                xmlsw.writeCharacters(s);
                lastWasElement=false;
            }
        }
        tok.skip("]");
        if(lastWasElement)ignorableSpacing(indent-3);
        xmlsw.writeEndElement();
   }

    private static char[] blanks = "\n".toCharArray();
    private static void ignorableSpacing(int nb) 
        throws XMLStreamException {
        if(nb>blanks.length){// extend the length of space array 
            blanks = new char[nb+1];
            blanks[0]='\n';
            Arrays.fill(blanks,1,blanks.length,' ');
        }
        xmlsw.writeCharacters(blanks, 0, nb+1);
    }

}

CompactTokenizer.java

import  java.io.Reader;
import  java.io.IOException;
import  java.io.StreamTokenizer;

public class CompactTokenizer {
    private StreamTokenizer st;

    CompactTokenizer(Reader r){
        st = new StreamTokenizer(r);
        st.resetSyntax(); // remove parsing of numbers...
        st.wordChars('\u0000','\u00FF'); // everything is part of a word
                                         // except the following...
        st.ordinaryChar('\n');
        st.ordinaryChar('[');
        st.ordinaryChar(']');
        st.ordinaryChar('@');
    }

    public String nextToken() throws IOException{
        st.nextToken();
        while(st.ttype=='\n'|| 
              (st.ttype==StreamTokenizer.TT_WORD && 
               st.sval.trim().length()==0))
            st.nextToken();
        return getToken();
    }

    public String getToken(){
        return (st.ttype == StreamTokenizer.TT_WORD) ? st.sval : (""+(char)st.ttype);
    }

    public String skip(String sym) throws IOException {
        if(getToken().equals(sym))
            return nextToken();
        else
            throw new IllegalArgumentException("skip: "+sym+" expected but"+ 
                                               sym +" found ");
    }
}

Для получения дополнительной информации вы можете ознакомиться с учебником

  1. https://docs.oracle.com/javase/tutorial /jaxp/stax/example.html
  2. http://www.ibm.com/developerworks/library/x-tipstx2/index.html
  3. http://www.iro.umontreal.ca/~lapalme/ForestInsteadOfTheTrees/HTML/ch09s03.html
  4. http: //staf.sourceforge .net / current / STAXDoc.pdf
6
ответ дан Community 26 August 2018 в 03:42
поделиться

Вчера я сделал что-то похожее, мне нужно добавить значение из unziped XML в потоке в базу данных.

//import I'm not sure if all are necessary :) 
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.*;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

//I didnt checked this code now because i'm in work for sure its work maybe 
you will need to do little changes
InputSource is = new InputSource(new FileInputStream("test.xml"));

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(is);
XPathFactory xpf = XPathFactory.newInstance();
XPath xpath = xpf.newXPath();
String words= xpath.evaluate("/foo/bar", doc.getDocumentElement());
ParsingHexToChar.parseToChar(words);

// lib which i use common-lang3.jar
//metod to parse 
public static String parseToChar( String words){

    String decode= org.apache.commons.lang3.StringEscapeUtils.unescapeHtml4(words);

        return decode;
 }
1
ответ дан David G. 26 August 2018 в 03:42
поделиться

Другой подход, поскольку в любом случае вы не используете жесткий OXM-подход. Возможно, вы захотите попробовать использовать менее жесткий парсер, такой как JSoup? Это остановит немедленные проблемы с недопустимыми схемами XML и т. Д., Но он просто передаст проблему в ваш код.

3
ответ дан Richard 26 August 2018 в 03:42
поделиться

Просто чтобы использовать другой подход к решению:

Вы можете огибать ваш входной поток потоком, который заменяет объекты каким-то юридическим.

Пока это взломать наверняка, это должно быть быстрым и простым решением (или, лучше сказать, обходным путем). Тем не менее, это не так элегантно и чисто, как внутреннее решение xml framework.

1
ответ дан rpy 26 August 2018 в 03:42
поделиться
Другие вопросы по тегам:

Похожие вопросы: