繁体   English   中英

如何在Java中为XML节点创建属性(xmlns:xsd)?

[英]How to create attribute (xmlns:xsd) to XML node in Java?

我目前正在用Java创建XML文档。 该文档应具有以下结构:

<?xml version="1.0" ?> 
<Cancelacion xmlns:xsd="http://www.w3.org/2001/XMLSchema"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             RfcEmisor="VSI850514HX4" 
             Fecha="2011-11-23T17:25:06" 
             xmlns="http://cancelacfd.sat.gob.mx">
    <Folios>
        <UUID>BD6CA3B1-E565-4985-88A9-694A6DD48448</UUID> 
    </Folios>
</Cancelacion>

我想知道是否存在使用xmlns:xsd表单创建属性的特殊方法? 我目前正在声明此属性,如下所示:

DocumentBuilderFactory dbfac = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder;
docBuilder = dbfac.newDocumentBuilder();
Document doc = docBuilder.newDocument();
doc.setXmlVersion("1.0");
doc.setXmlStandalone(true);

Element cancelacion = doc.createElement("Cancelacion");
cancelacion.setAttribute("xmlns", "http://cancelacfd.sat.gob.mx");
cancelacion.setAttribute("xmlns:xsd", "http://www.w3.org/2001/XMLSchema");
cancelacion.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
cancelacion.setAttribute("RfcEmisor", rfc);
cancelacion.setAttribute("Fecha", fecha);

解决我的问题是编写如下代码:

//Crear un document XML vacío
DocumentBuilderFactory dbfac = DocumentBuilderFactory.newInstance();
dbfac.setNamespaceAware(true);
DocumentBuilder docBuilder;
docBuilder = dbfac.newDocumentBuilder();
DOMImplementation domImpl = docBuilder.getDOMImplementation();
Document doc = domImpl.createDocument("http://cancelacfd.sat.gob.mx", "Cancelacion", null);
doc.setXmlVersion("1.0");
doc.setXmlStandalone(true);

Element cancelacion = doc.getDocumentElement();
cancelacion.setAttributeNS("http://www.w3.org/2000/xmlns/","xmlns:xsd","http://www.w3.org/2001/XMLSchema");
cancelacion.setAttributeNS("http://www.w3.org/2000/xmlns/","xmlns:xsi","http://www.w3.org/2001/XMLSchema-instance");
cancelacion.setAttribute("RfcEmisor", rfc);
cancelacion.setAttribute("Fecha", fecha);

Element folios = doc.createElement("Folios");
cancelacion.appendChild(folios);
for (int i=0; i<uuid.length; i++) {
    Element u = doc.createElement("UUID");
    u.setTextContent(uuid[i]);
    folios.appendChild(u);
}

为什么文件应具有您建议的结构? 您在声明带有前缀的名称空间,但是示例输出在这些名称空间中不包含任何元素。 因此,这些声明是不必要的。

首先,了解xmlns (或xmlns:prefix )是用于声明名称空间的保留XML伪属性。 这不是正常的属性。 其次,只要您首先在所需的名称空间中创建元素,文档中的名称空间声明的位置就不必担心。

让序列化程序决定将名称空间声明放在何处。

在正确的名称空间中注册元素,如下所示:

Element cancelacion = doc.createElementNS(
        "http://cancelacfd.sat.gob.mx", "Cancelacion");
doc.appendChild(cancelacion);

Element child = doc.createElementNS("http://cancelacfd.sat.gob.mx",
        "SomeChild");
cancelacion.appendChild(child);

序列化时:

DOMSource domSource = new DOMSource(doc);
StreamResult streamResult = new StreamResult(System.out);
TransformerFactory tf = TransformerFactory.newInstance();
Transformer serializer = tf.newTransformer();
serializer.transform(domSource, streamResult); 

结果:

<Cancelacion xmlns="http://cancelacfd.sat.gob.mx">
    <SomeChild/>
</Cancelacion>

请注意, CancelacionSomeChild以完全相同的方式创建,但只有Cancelacion包含命名空间声明(因为声明适用于所有后代)。 串行器为我们处理了此问题。

警告: 接下来是黑客。 我不建议使用它。 这可能会给您带来麻烦。 您可能应该停止阅读。 但是...如果您别无选择,它可能会起作用。

如果您不顾一切,可以手动拼接未使用的名称空间。 (将XML作为字符串处理几乎总是一个坏主意。)

首先,将结果保存在可以转换为StringOutputStream中:

ByteArrayOutputStream out = new ByteArrayOutputStream();
DOMSource domSource = new DOMSource(doc);
StreamResult streamResult = new StreamResult(out);
TransformerFactory tf = TransformerFactory.newInstance();
Transformer serializer = tf.newTransformer();
serializer.setOutputProperty(OutputKeys.INDENT, "yes");
serializer.transform(domSource, streamResult);

然后将名称空间声明放入其中,而不考虑什么是好的,正确的和体面的:

String[] parts = out.toString().split("\\\">", 2);
String result = parts[0] + 
    " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"" +
    " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" + parts[1];

xmlns:xsd不是属性,而是名称空间声明

DOM应该在需要时创建这些声明。

使用createElementNScreateAttributeNS方法将导致创建名称空间声明,但是您需要了解XML名称空间

在您的示例中,未使用绑定到xsd和xsi的名称空间,因此是多余的。 但是, Cancelacion元素位于默认名称空间中,该名称空间由您提供的XML中的xmlns="http://cancelacfd.sat.gob.mx"声明定义。

因此,您应该使用:

doc.createElementNS("http://cancelacfd.sat.gob.mx", "Cancelacion");

创建那个。 请注意,就文档的含义而言,名称空间前缀(或缺少名称空间)无关紧要。

在我的代码中,我写道:

    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    DocumentBuilder builder = factory.newDocumentBuilder();
    Document document = builder.newDocument();

    Element spectraexchage = document.createElementNS("http://www.lstelcom.com/Schema/SPECTRAexchange", "SPECTRAEXCHANGE");
    spectraexchage.setAttribute("xmlns:xsd", "http://www.w3.org/2001/XMLSchema");
    spectraexchage.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
    spectraexchage.setAttribute("version", "2.4.28");
    document.appendChild(spectraexchage);

    DOMSource source = new DOMSource(document);
    StreamResult result = new StreamResult(System.out);
    transformer.transform(source, result);

输出:

<SPECTRAEXCHANGE xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.4.28" xmlns="http://www.lstelcom.com/Schema/SPECTRAexchange">

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM