【问题标题】:Generating part of XML with namespaces with XOM使用 COM 生成带有名称空间的部分 XML
【发布时间】:2013-01-11 05:48:07
【问题描述】:

虽然描述看起来很长,但实际上很简单。

我需要什么

我有以下 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 基本上包含三个命名空间

现在我需要生成另一个单个 atom:entry 节点的 xml 文档。如下所示

<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:identifier 缺少命名空间。

我非常需要帮助才能摆脱这个问题。期待任何帮助。

【问题讨论】:

    标签: java xml xml-namespaces xom


    【解决方案1】:

    没有问题。 dcterms 命名空间在需要的地方声明:在 dcterms:identifier 标签中

    <dcterms:identifier xmlns:dcterms="http://purl.org/dc/terms/">
    

    其实你期待的xml和你得到的xml是一样的。命名空间没有在同一个地方声明这一事实不会影响 xml 内容的含义。

    =======更新========

    我建议解决真正的问题,即您的系统不接受有效的 xml(或者它没有正确解释它们)这一事实。作为解决您的情况的方法,请尝试以下代码:

    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));
                }
            }
        }
    

    基本上,上面的代码会遍历所有子节点,识别命名空间并将其作为命名空间声明添加到根。我已经尝试过并且工作过。我希望它能解决您的问题

    【讨论】:

    • 你是对的。但问题是我正在使用的系统需要根元素中的所有命名空间声明。不是那个特定的元素。所以我需要一种方法来移动根节点的声明。
    • 完全同意你的看法。如果我能解决“真正的问题”,没有人会比我更快乐。但它超出了我的范围。无论如何,您的解决方案似乎很有希望。我会试试看。我下周一回来。
    【解决方案2】:

    你想要

    doc.getRootElement().addNamespaceDeclaration("dcterms", "http://purl.org/dc/terms/");
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-02-20
      • 1970-01-01
      • 1970-01-01
      • 2017-03-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多