使用Jersey构建XML响应

时间:2012-07-18 13:55:49

标签: java xml jersey

我正在尝试构建一个Jersey Web服务,它将接收数据,将其格式化为XML文档,然后将其传递给另一个服务。我意识到Jersey does have XML support,但由于项目所需的XML结构,我在实现它时遇到了一些麻烦。所需的输出如下所示:

<root-element>
    <table>
        <row>
            <d>data1</d>
            <d>data2</d>
            <d>data3</d>
        </row>
        <row>
            <d>data4</d>
            <d>data5</d>
            <d>data6</d>
        </row>
    </table>

我的问题出现了,<d><row>元素的数量可变,这些元素将根据传入的数据确定。我知道我可以使用@XmlRootElement格式化一个简单的表格在处理数据的类之上,但这可能仅对我的<root-element>有用,因为元素只会填充其他元素。我知道我需要使用某种循环来创建每个<row>,但我不确定如何在每个字段中创建具有不同数据的每个<d>元素。有什么建议吗?

3 个答案:

答案 0 :(得分:5)

您可以使用带有JAXB (JSR-222)注释的Java模型来支持您的用例。可能出现多次的元素将对应于Java模型中的List属性。下面是一个如何映射文档的示例。

表格

我们将使用@XmlElementWrapper注释添加分组元素,使用@XmlElement注释来设置集合中项目的元素名称。

package forum11543081;

import java.util.List;
import javax.xml.bind.annotation.*;

@XmlRootElement(name="root-element")
@XmlAccessorType(XmlAccessType.FIELD)
public class Table {

    @XmlElementWrapper(name="table")
    @XmlElement(name="row")
    private List<Row> rows;

}

<强>行

如果属性/字段的名称与生成的XML元素的名称匹配,则不需要任何注释。

package forum11543081;

import java.util.List;
import javax.xml.bind.annotation.*;

@XmlAccessorType(XmlAccessType.FIELD)
public class Row {

    private List<String> d;

}

<强>演示

下面是一个独立的示例,用于证明映射有效:

package forum11543081;

import java.io.File;
import javax.xml.bind.*;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(Table.class);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        File xml = new File("src/forum11543081/input.xml");
        Table table = (Table) unmarshaller.unmarshal(xml);

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(table, System.out);
    }

}

<强> input.xml中/输出

<root-element>
    <table>
        <row>
            <d>data1</d>
            <d>data2</d>
            <d>data3</d>
        </row>
        <row>
            <d>data4</d>
            <d>data5</d>
            <d>data6</d>
        </row>
    </table>
</root-element>

了解更多信息

答案 1 :(得分:1)

如果要将默认的Jersey / JAXB编组用于XML,您将构建一个反映您所指示的结构的模式,其中包括集合(无界元素)并生成(使用xjc)相应的Java类。您的restful服务的响应将是与根元素关联的类型,您将构建该结构作为服务的一部分。无界元素呈现为java列表,因此它们可以是任意数量的元素。在代码中你只需要.add(元素)。类似的东西:

<schema ...>
...
  <element name="root-element">
    <complexType>
      <sequence>
        <element name="table" type="tns:TableType" />
      </sequence>
    </complexType>
  </element>

  <complexType name="TableType">
    <sequence>
      <element name="row" minOccurs="0" maxOccurs="unbounded" type="tns:RowType" />
    </sequence>
  </complexType>

  <complexType name="RowType">
    <sequence>
      <element name="d" minOccurs="0" maxOccurs="unbounded" type="string" />
    </sequence>
  </complexType>
</schema>

替代方法是(如TedTrippin所述)使用stax(流处理器)通过标记在适当的位置构建xml文档标记并返回最终结果。

答案 2 :(得分:-2)

我最终做了什么:

由于我有来自另一个项目的代码,我可以重复使用它来循环遍历XML构建,我决定在文档中构建XML,然后将该文档写入字符串,如下所示:

public class XmlHandler{
    public static String buildXml(){
        String xmlString="";

        //Create XML Document
        DocumentBuilderFactory docfac = DocumentBuilderFactory.newInstance();
        DocumentBuilder docbuil = null;
        docbuil = docfac.newDocumentBuilder();
        Document doc = docbuil.newDocument();

        //Build XML Elements
        Element root = doc.createElement("root-element");
        doc.appendChild(root);      
        Element table = doc.createElement("table");
        root.appendChild(table);

        //Hard coded data here for testing purposes.
        String[][]array={
        {"data1", "data2", "data3"},
        {"data4", "data5", "data6"}
        };

        Text text = null;
        Element d = null;
        Element row = null;
        for(String[] line : array)
        {
            row=doc.createElement("row");
            table.appendChild(row);
            for(String label : line)
            {
                d = doc.createElement("d");
                row.appendChild(d);
                text = doc.createTextNode(label);
                d.appendChild(text);
                }
            }
        }

        //Write Document to String
        DOMImplementationLS domImplLS = (DOMImplementationLS) doc.getImplementation();
        LSSerializer serializer = domImplLS.createLSSerializer();
        serializer.getDomConfig().setParameter("format-pretty-print", true);
        LSOutput output = domImplLS.createLSOutput();
        output.setEncoding("UTF-8");
        StringWriter sw = new StringWriter();
        output.setCharacterStream(sw);
        serializer.write(doc, output);
        xmlString = sw.toString();

        return xmlString;
    }
}

虽然硬编码的String数组不会存在很长时间,但直到我找到需要传递的数据类型,这个类才能正常工作。