Генерация части 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 содержит в основном три пространства имен

Теперь мне нужно сгенерировать еще один 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/");
Другие вопросы по тегам