xmlns 已经绑定到 .重新绑定到 http://entreprise.uk/ns 是一个错误

xmlns has been already bound to . Rebinding it to http://entreprise.uk/ns is an error

我正在使用 spring 批处理生成 xml 个文件。

我的作家长这样:

Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setClassesToBeBound(Person.class);

StaxEventItemWriter<Person> itemWriter = new StaxEventItemWriter<>();
itemWriter.setRootTagName("Persons");
itemWriter.setMarshaller(marshaller);
itemWriter.setRootElementAttributes(new HashMap<String, String>() {{
        put("xmlns", "http://entreprise.uk/ns");
}});
itemWriter.setResource(new FileSystemResource(Paths.get("personOutput.xml").toFile()));
itemWriter.afterPropertiesSet();

return itemWriter;

那个人 class :

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "Person")
public class Person {
  //...
}

当我 运行 批处理时出现此错误:

Caused by: javax.xml.stream.XMLStreamException: xmlns has been already bound to . Rebinding it to http://entreprise.uk/ns is an error

有人知道怎么解决吗?我需要在根元素处看到 xmlns 属性,例如:

<?xml version="1.0" encoding="UTF-8"?>
<Persons xmlns="http://entreprise.uk/ns">
    <person>...</person>
</Persons>

我正在使用 spring-boot-starter-batch:2.3.5.RELEASE

我个人会选择一个名为 Persons 的容器 class,它有一个 array/list Person。

@XmlRootElement(name = "Persons", namespace = "http://entreprise.uk/ns")
@XmlAccessorType(XmlAccessType.FIELD)
public class Persons {

  @XmlElement(name = "Person")
  private List<Person> persons;

  //...
}

这也应该消除了您当前必须设置的一些配置的需要。

有两种方法可以解决这个问题:

方法一 使用包信息文件:

XML:

<?xml version="1.0" encoding="UTF-8"?>
<Persons xmlns="http://entreprise.uk/ns">
    <person>
        <firstName>Batman</firstName>
    </person>
</Persons>

包-info.java:

@XmlSchema(
        elementFormDefault = XmlNsForm.QUALIFIED,
        namespace = "http://entreprise.uk/ns",
        xmlns = {@XmlNs(prefix = "", namespaceURI = "http://entreprise.uk/ns")})
package stackover;

import jakarta.xml.bind.annotation.XmlNs;
import jakarta.xml.bind.annotation.XmlNsForm;
import jakarta.xml.bind.annotation.XmlSchema;

人数:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "Persons")
@Data
public class Persons {
    private Person person;
}

人:

@Data
@XmlAccessorType(XmlAccessType.FIELD)
public class Person {
    private String firstName;
}

主要:


public class Main {
    public static void main(String[] args) throws JAXBException, XMLStreamException {
        final InputStream inputStream = Main.class.getClassLoader().getResourceAsStream("students.xml");
        final XMLStreamReader xmlStreamReader = XMLInputFactory.newInstance().createXMLStreamReader(inputStream);
        final Unmarshaller unmarshaller = JAXBContext.newInstance(Persons.class).createUnmarshaller();
        final Persons persons = unmarshaller.unmarshal(xmlStreamReader, Persons.class).getValue();
        System.out.println(persons.toString());

        Marshaller marshaller = JAXBContext.newInstance(Persons.class).createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
        marshaller.marshal(persons, System.out);
    }
}

输出:

Persons(person=Person(firstName=Batman))
<Persons xmlns="http://entreprise.uk/ns">
   <person>
      <firstName>Batman</firstName>
   </person>
</Persons>

方法二 使用带名称空间 URI 的前缀 XML 并添加到根 class:

XML:

<?xml version="1.0" encoding="UTF-8"?>
<Persons xmlns:ns0="http://entreprise.uk/ns">
    <person>
        <firstName>Batman</firstName>
    </person>
</Persons>

人数:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "Persons", namespace = "http://entreprise.uk/ns")
@Data
public class Persons {
    private Person person;
}

人:

@Data
@XmlAccessorType(XmlAccessType.FIELD)
public class Person {
    private String firstName;
}

主要:

public class Main {
    public static void main(String[] args) throws JAXBException, XMLStreamException {
        final InputStream inputStream = Main.class.getClassLoader().getResourceAsStream("students.xml");
        final XMLStreamReader xmlStreamReader = XMLInputFactory.newInstance().createXMLStreamReader(inputStream);
        final Unmarshaller unmarshaller = JAXBContext.newInstance(Persons.class).createUnmarshaller();
        final Persons persons = unmarshaller.unmarshal(xmlStreamReader, Persons.class).getValue();
        System.out.println(persons.toString());

        Marshaller marshaller = JAXBContext.newInstance(Persons.class).createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
        marshaller.marshal(persons, System.out);
    }
}

输出:

Persons(person=Person(firstName=Batman))
<ns0:Persons xmlns:ns0="http://entreprise.uk/ns">
   <person>
      <firstName>Batman</firstName>
   </person>
</ns0:Persons>

要在根级别添加命名空间,您必须修改配置中的 rootTagName。

rootTagName("{http://entreprise.uk/ns}Persons")

希望这能解决您的问题。