#java #xmlstreamwriter
#java #xmlstreamwriter
Вопрос:
Я получаю это исключение:
javax.xml.stream.XMLStreamException: Attribute not associated with any element
at com.sun.xml.internal.stream.writers.XMLStreamWriterImpl.writeAttribute(Unknown Source)
at de.dhbw.horb.routePlanner.parser.GraphDataParser$2.run(GraphDataParser.java:136)
at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
at java.util.concurrent.FutureTask.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)*
Из моего кода ниже.
Я просто не понимаю, откуда он берется.
public void writeEdgeXML() throws XMLStreamException {
final long[] idCount = new long[1];
XMLOutputFactory factory = XMLOutputFactory.newInstance();
try {
final XMLStreamWriter writer = factory
.createXMLStreamWriter(new FileOutputStream(
GraphDataConstants.CONST_XML_EDGE), "UTF-8");
writer.writeStartDocument("UTF-8", "1.0");
while (graphSR.hasNext()) {
if (graphSR.nextStartElement() amp;amp; graphSR.isWay()) {
final Way nextWay = getWay(null);
Controller.executor.getExecutor().submit(new Runnable() {
@Override
public void run() {
while (nextWay != null amp;amp; nextWay.hasEdge()) {
try {
idCount[0] ;
Edge e = nextWay.removeFirstEdge();
writer.writeStartElement(GraphDataConstants.CONST_EDGE);
writer.writeAttribute(
GraphDataConstants.CONST_EDGE_ID,
String.valueOf(idCount[0]));
writer.writeEmptyElement(GraphDataConstants.CONST_EDGE_NODE);
writer.writeAttribute(
GraphDataConstants.CONST_EDGE_ID,
String.valueOf(e.getStartNode()
.getID()));
writer.writeAttribute(
GraphDataConstants.CONST_EDGE_LATITUDE,
String.valueOf(e.getStartNode()
.getLatitude()));
writer.writeAttribute(
GraphDataConstants.CONST_EDGE_LONGITUDE,
String.valueOf(e.getStartNode()
.getLongitude()));
writer.writeEndElement();
writer.flush();
} catch (XMLStreamException e) {
e.printStackTrace();
}
}
}
});
}
}
Комментарии:
1. в de.dhbw.horb.routePlanner.parser. GraphDataParser$2.выполнить(GraphDataParser.java:136)
2. Вероятно, вы не сможете записать атрибут после
writeEmptyElement
. Должны ли атрибуты относиться к пустому элементу или к окружающему элементу?3. @rahul pasricha::D спасибо, что рассказали мне, что я могу прочитать в исключении. Я могу понять исключения. Проблема в том, что это не имеет для меня никакого смысла.
4. @JimGarrison: это должно выглядеть так: <идентификатор ребра = «1»><идентификатор узла = «324» широта =»59.3″ длина =»6.0″/><идентификатор узла = «325» широта =»59.4″ длина =»6.1″/> </edge>
5. Я только что попробовал … мой предыдущий комментарий был неверным, вы можете добавить атрибуты к пустому элементу.
Ответ №1:
XMLStreamWriter
не является потокобезопасным.
Вы создаете один XMLStreamWriter
, а затем пытаетесь использовать его для записи элементов в несколько потоков одновременно. Это не гарантирует, что будет работать вообще, и если это произойдет, созданные вами элементы и атрибуты не обязательно окажутся там, где вы их ожидали. Я подозреваю, что ошибка связана с условием гонки в соответствии с
Thread 1 Thread 2
-------- --------
1) emptyElement
2) attribute
3) emptyElement
4) endElement
5) attribute (BANG!)
Вам необходимо сериализовать все записи XML в один поток.
Комментарии:
1. Это тоже мое предположение. Но как сериализовать в один поток? Разве это не замедляет его?
2. @besnep на самом деле у вас нет выбора. Если
removeFirstEdge
бы это была дорогостоящая операция, тогда могло бы иметь смысл иметь несколько потоков и просто синхронизировать бит записи XML от начала до конца пограничного элемента, но этот бит определенно должен быть однопоточным. ЕслиremoveFirstEdge
это дешево, то вы могли бы также выполнить весь процесс в одном потоке и избавиться от накладных расходов на переключение контекста.