Генерация части XML с пространствами имен с помощью XOM
Хотя описание выглядит очень длинным, на самом деле оно довольно простое.
Что мне нужно
У меня есть следующий документ XML
<?xml version="1.0" encoding="UTF-8"?>
<atom:feed xmlns:opensearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:dcterms="http://purl.org/dc/terms/" xmlns:atom="http://www.w3.org/2005/Atom" type="application/atom+xml;type=feed">
<atom:link rel="self" href="http://hostname/thirdparty/playlist"/>
<atom:id>vuter id</atom:id>
<atom:title>Untitled</atom:title>
<opensearch:totalResults>249</opensearch:totalResults>
<opensearch:startIndex>1</opensearch:startIndex>
<opensearch:itemsPerPage>249</opensearch:itemsPerPage>
<atom:entry type="application/atom+xml;type=entry">
<atom:id>12345678</atom:id>
<atom:title>Playlist example 1</atom:title>
<atom:link rel="self" type="application/atom+xml;type=entry" href="http://hostname/thirdparty/playlist/2101211130000011141"/>
<dcterms:identifier>2101211130000011141</dcterms:identifier>
</atom:entry>
<atom:entry type="application/atom+xml;type=entry">
<atom:id>12345678</atom:id>
<atom:title>Playlist example 2</atom:title>
<atom:link rel="self" type="application/atom+xml;type=entry" href="http://hostname/thirdparty/playlist/2101211090000000341"/>
<dcterms:identifier>2101211090000000341</dcterms:identifier>
</atom:entry>
</atom:feed>
Обратите внимание, что xml содержит в основном три пространства имен
- Атом: http://www.w3.org/2005/Atom
- dcterms: http://purl.org/dc/terms/
- opensearch: http://a9.com/-/spec/opensearch/1.1/
Теперь мне нужно сгенерировать еще один XML-документ из одного узла atom: entry. Как ниже
<atom:entry type="application/atom+xml;type=entry" xmlns:opensearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:dcterms="http://purl.org/dc/terms/" xmlns:atom="http://www.w3.org/2005/Atom">
<atom:id>12345678</atom:id>
<atom:title>Playlist example 1</atom:title>
<atom:link rel="self" type="application/atom+xml;type=entry" href="http://hostname/thirdparty/playlist/2101211130000011141"/>
<dcterms:identifier>2101211130000011141</dcterms:identifier>
</atom:entry>
Что я получаю
Я использую XOM и до сих пор я пытался с
Element rootElem = new Builder().build(ins).getRootElement();
xc = XPathContext.makeNamespaceContext(rootElem);
Element firstEntry = (Element) rootElem.query("atom:entry", xc).get(0);
Document doc = new Document((Element)firstEntry.copy());
System.out.println(doc.toXML());
И я получаю следующий XML только с одним объявлением пространства имен. Как ниже.
<?xml version="1.0"?>
<atom:entry xmlns:atom="http://www.w3.org/2005/Atom" type="application/atom+xml;type=entry">
<atom:id>12345678</atom:id>
<atom:title>Playlist example 1</atom:title>
<atom:link rel="self" type="application/atom+xml;type=entry" href="http://hostname/thirdparty/playlist/2101211130000011141" />
<dcterms:identifier xmlns:dcterms="http://purl.org/dc/terms/">2101211130000011141</dcterms:identifier>
</atom:entry>
проблема
Он содержит только пространство имен Atom:(Следовательно, он не является допустимым XML. Потому что у него есть дочерний узел dcterms: идентификатор, чье пространство имен отсутствует.
Мне очень нужна помощь, чтобы выйти из этой проблемы. Ждем любую помощь.
2 ответа
Там нет проблем. Пространство имен dcterms объявляется там, где это необходимо: в теге dcterms: identifier
<dcterms:identifier xmlns:dcterms="http://purl.org/dc/terms/">
На самом деле, xml, который вы ожидаете, и тот, который вы получаете, совпадают. Тот факт, что пространства имен не объявляются в одном и том же месте, не влияет на значение содержимого XML.
======= ========UPDATE
Я бы посоветовал решить реальную проблему, то есть тот факт, что ваша система не принимает действительные xmls (или неправильно интерпретирует их). Для исправления ситуации попробуйте следующий фрагмент кода:
Element rootElem = new Builder().build(ins).getRootElement();
XPathContext xc = XPathContext.makeNamespaceContext(rootElem);
Element firstEntry = (Element) rootElem.query("atom:entry", xc).get(0);
Document doc = new Document((Element)firstEntry.copy());
Element root = doc.getRootElement();
recursive(root,root);
static void recursive(Element root, Element child){
root.addNamespaceDeclaration(child.getNamespacePrefix(), child.getNamespaceURI());
if (child.getChildElements().size()>0){
int i = child.getChildElements().size();
for (int k=0;k<i;k++){
recursive(root,child.getChildElements().get(k));
}
}
}
В основном код выше проходит через все дочерние элементы, идентифицирует там пространство имен и добавляет его в корень как объявление пространства имен. Я попробовал это и работал. Я надеюсь, что это поможет решить вашу проблему
Ты хочешь
doc.getRootElement().addNamespaceDeclaration("dcterms", "http://purl.org/dc/terms/");