Этот вопрос довольно старый, так как современное обновление. С наступлением 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 , чтобы узнать больше.
Для этой цели я бы использовал библиотеку Jsoup. Я проверил следующее ниже, и он работает. Я не знаю, поможет ли это. Он может быть расположен здесь: http://jsoup.org/download
public static void main(String args[]){
String html = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><foo>" +
"<bar>Some text — invalid!</bar></foo>";
Document doc = Jsoup.parse(html, "", Parser.xmlParser());
for (Element e : doc.select("bar")) {
System.out.println(e);
}
}
Результат:
<bar>
Some text — invalid!
</bar>
Загрузка из файла может быть найдено здесь:
Проблема - 1: Мне нужно разобрать кучу XML-файлов на Java, которые иногда и недействительно содержат HTML-объекты, такие как
blockquote>—
. XML имеет только пять предопределенных объектов .
—
,
не входит в их число. Он работает только при использовании в простом HTML или в устаревшем JSP. Таким образом, SAX не поможет. Это можно сделать, используяStaX
, который имеет API-интерфейс с высоким уровнем итератора. [Собрано из этой ссылки )Проблема - 2: Я обнаружил, что могу переопределить resolveEntity в org.xml.sax.helpers.DefaultHandler, но как использовать это с API более высокого уровня?
blockquote>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 text — invalid!</bar> </foo>
Выход:
Ссылка на объект: nbsp
Ссылка на объект: mdash
blockquote>Кредит отправляется на
@skaffman
.Ссылки по теме:
- http://www.journaldev.com/1191/how-to-read-xml-file-in-java-using-java-stax-api
- http://www.journaldev.com/1226/java-stax-cursor-based-api-read-xml-example
- http: // www. vogella.com/tutorials/JavaXML/article.html
- Существует ли Java XML API, который может анализировать документ без разрешения объектов символов?
UPDATE:
Проблема - 3: Есть ли способ использовать StaX для «фильтрации» сущностей (например, заменяя их чем-то другим) и все еще обрабатывать документ в конце процесса?
blockquote>Чтобы создать новый документ с использованием API StAX, необходимо создать
XMLStreamWriter
, который предоставляет методы для создания XML-открывания и закрытия теги, атрибуты и содержание символов.Для документа существует 5 методов
XMLStreamWriter
.
xmlsw.writeStartDocument();
- инициализирует пустой документ, к которому можно добавить элементыxmlsw.writeStartElement(String s)
- создает новый элемент с именем sxmlsw.writeAttribute(String name, String value)
- добавляет имя атрибута с соответствующим значением последнему элементу, создаваемому вызовом writeStartElement. Можно добавлять атрибуты до тех пор, пока не будет выполнен вызов writeElementStart, writeCharacters или writeEndElement.xmlsw.writeEndElement
- закрыть последний начатый элемент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 "); } }
Для получения дополнительной информации вы можете ознакомиться с учебником
Вчера я сделал что-то похожее, мне нужно добавить значение из 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;
}
Другой подход, поскольку в любом случае вы не используете жесткий OXM-подход. Возможно, вы захотите попробовать использовать менее жесткий парсер, такой как JSoup? Это остановит немедленные проблемы с недопустимыми схемами XML и т. Д., Но он просто передаст проблему в ваш код.
Просто чтобы использовать другой подход к решению:
Вы можете огибать ваш входной поток потоком, который заменяет объекты каким-то юридическим.
Пока это взломать наверняка, это должно быть быстрым и простым решением (или, лучше сказать, обходным путем). Тем не менее, это не так элегантно и чисто, как внутреннее решение xml framework.