在JDOM2中创建属性为xsi:type的XML节点

时间:2017-06-22 15:10:52

标签: java xml jdom-2

我正在尝试创建以下XML文档。

<?xml version="1.0" encoding="UTF-8"?>
<BCPFORMAT>
  <RECORD>
    <FIELD ID="1" xsi:type="CharFixed" MAX_LENGTH="4" />
  </RECORD>
</BCPFORMAT>

我使用Java代码如下 -

package com.tutorialspoint.xml;

import java.awt.List;
import java.io.File;
import java.io.FileWriter;
import java.util.ArrayList;

import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;

import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.output.Format;
import org.jdom2.output.XMLOutputter;

public class createXmlLayout {
    public static void main(String[] args) {
        Document doc = new Document();
        Element root = new Element("BCPFORMAT");
        //RECORD Element
        Element child = new Element("RECORD");
        //FIELD Element
        Element name = new Element("FIELD")
                .setAttribute("ID", "1")
                .setAttribute("xsi:type", "CharFixed")
                .setAttribute("MAX_LENGTH", "4");

        child.addContent(name);
        root.addContent(child);
        doc.addContent(root);

        XMLOutputter outputter = new XMLOutputter(Format.getPrettyFormat());
        try {
            outputter.output(doc, System.out);
            outputter.output(doc, new FileWriter("c:\\VTG_MAPN.xml"));

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

但我收到以下错误:

  

名称&#34; xsi:type&#34;对于JDOM / XML属性是不合法的:XML名称&x; xsi:type&#39;不能包含字符&#34;:&#34;。

我知道我可能需要使用命名空间,但我无法弄明白。

1 个答案:

答案 0 :(得分:1)

由于 : 上的XML 1.0规范,JDOM不允许您以这种方式创建包含冒号( : )的路径保留给命名空间。 Check JDOM's FAQ here.

要设置或创建使用命名空间的属性,必须使用接受命名空间作为参数的函数/构造函数。

在这种情况下,您可以使用以下内容:

e.setAttribute("type", "CharFixed", Namespace.getNamespace("xsi", "xsi_uri"));

<强>更新

我们可以在子项的父项之一(FIELD)中添加名称空间声明,并将子项设置为对给定属性使用此名称空间。

Namespace namespace = Namespace.getNamespace("xsi", "xsi_uri");
root.addNamespaceDeclaration(namespace);
// ...

Element name = new Element("FIELD")
        .setAttribute("ID", "1")
        .setAttribute("type", "CharFixed", root.getNamespacesInScope().get(2))
        .setAttribute("MAX_LENGTH", "4");

// ...

输出如下:

<?xml version="1.0" encoding="UTF-8"?>
<BCPFORMAT xmlns:xsi="xsi_uri">
  <RECORD>
    <FIELD ID="1" xsi:type="CharFixed" MAX_LENGTH="4" />
  </RECORD>
</BCPFORMAT>

此功能是NamespaceAware Interface

的一部分

为什么get(2)

如果我们获得根元素的继承命名空间列表,它将返回3个命名空间,由以下文本描述:

[Namespace: prefix "" is mapped to URI ""]
[Namespace: prefix "xml" is mapped to URI "http://www.w3.org/XML/1998/namespace"]
[Namespace: prefix "xsi" is mapped to URI "xsi_uri"]

因此,索引0是空名称空间,索引1是默认的XML名称空间,最后,索引2是xsi的添加名称空间。

当然,我们不想对所需命名空间的索引进行硬编码,因此,我们可以事先执行以下操作来缓存所需的命名空间:

Namespace xsiNamespace =
        root.getNamespacesInScope().stream()        // Streams the namespaces in scope
        .filter((ns)->ns.getPrefix().equals("xsi")) // Search for a namespace with the xsi prefix
        .findFirst()                                // Stops at the first find
        .orElse(namespace);                         // If nothing was found, returns 
                                                    // the previously declared 'namespace' object instead.

使用缓存的命名空间:

// ...
.setAttribute("type", "CharFixed", xsiNamespace)
// ...