JAXB如果只有一个属性,则使用没有关闭标记的根元素

时间:2014-08-27 20:03:33

标签: java xml jaxb moxy

我正在使用JAXB / Moxy将类编组为XML。当根元素只包含一个属性时,输出如下:

    <?xml version="1.0" encoding="UTF-8"?>
    <procedure xmlns="http://xml.test.com/api/request" name="TestProcedure"/>

所需的输出包含过程的结束标记:

   <?xml version="1.0" encoding="UTF-8"?>
   <procedure xmlns="http://xml.test.com/api/request" name="TestProcedure"></procedure>

这将被发送到第三方系统。即使两者都是格式良好的XML,它仍然需要结束标记。

我看过这篇文章:JAXB marshals XML differently to OutputStream vs. StringWriter 但是在本地运行时没有看到输出流和字符串之间的输出有差异。

这似乎只处理元素和属性,但不处理根元素: Represent null value as empty element in xml jaxb 我仍然设置了一个DescriptorCustomizer并查看了调试器中的ClassDescriptor,但是没有看到像XMLDirectMapping那样设置的任何属性。

我的域对象看起来像

   @XmlRootElement(name = "procedure")
   public class ProcRequest {
    protected String procName;
    protected String requestId;
    protected List<Param> parameter;

    @XmlAttribute
    public String getProcName() {
        return procName;
    }
    public void setProcName(String procName) {
        this.procName = procName;
    }
    @XmlAttribute
    public String getRequestId() {
        return requestId;
    }
    public void setRequestId(String requestId) {
        this.requestId = requestId;
    }
    @XmlElement
    public List<Param> getParam() {
        if (this.param == null) {
            this.param = new ArrayList<Param>();
        } 

        return param;
    }
    public void setParam(List<Param> param) {
        this.param = param;
    }

   }

我的服务包含:

   ProcRequest procRequest = new ProcRequest();
   procRequest.setProcName("TestProcedure");

   JAXBContext jaxbContext = JAXBContext.newInstance(ProcRequest.class);

   Marshaller moxyMarshaller = jaxbContext.createMarshaller();
   moxyMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

   moxyMarshaller.marshal(procRequest, System.out);

是否有任何属性或属性可以设置为强制结束标记在末尾类似于Marshaller.JAXB_FORMATTED_OUTPUT? 还是其他任何建议?

2 个答案:

答案 0 :(得分:3)

由于这两种形式在语义上是等效的XML:

  1. 标准的JAXB封送程序不提供控制此细节的选项;和
  2. 任何解决方案都必须在XML处理之外。
  3. 除非您可以使用允许自定义空标记的其他JAXB或封送程序实现,否则我相信您会被卡住。我认为撒克逊曾经有过这样的选择,但多年来没有看过。

答案 1 :(得分:0)

Jim带着我在第2点的最后方向带领我。我最终在Woodstox属性上用一个丑陋的黑客手动处理它。您可以手动指定哪些属性可以使用自动关闭语法。在调试时我意外地给它一个空的属性集,并且所有属性都有一个单独的结束标记。

XMLOutputFactory outputFactory = XMLOutputFactory.newInstance();
Set<String> tags = new HashSet<String>();
// This specifies the procedure field should be allowed to use the self-closing syntax instead of having a separate end tag
//tags.add("procedure"); 
outputFactory.setProperty(WstxOutputProperties.P_OUTPUT_EMPTY_ELEMENT_HANDLER, new EmptyElementHandler.SetEmptyElementHandler(tags));  
StringWriter sw = new StringWriter();
XMLStreamWriter writer = outputFactory.createXMLStreamWriter(sw);

writer.writeStartDocument("1.0");
writer.writeStartElement("procedure");
writer.writeAttribute("name", procRequest.getName());
writer.writeAttribute("requestId", procRequest.getRequestId());
writer.writeEndElement();
writer.writeEndDocument();
writer.flush();
sw.flush();