2

我正在尝试构建一个 Jersey Web 服务,它将接收数据,将其格式化为 XML 文档,然后将其传递给另一个服务。我意识到Jersey 确实支持 XML,但是由于项目所需的 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>的,因为该元素只会填充其他元素。我知道我需要使用某种循环来创建 each <row>,但我不确定如何<d>在每个字段中创建具有不同数据的每个元素。有什么建议么?

4

3 回答 3

5

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

桌子

我们将使用@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);
    }

}

输入.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>

了解更多信息

于 2012-07-19T09:55:14.280 回答
1

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

<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 文档标记,并在适当的位置使用循环并返回最终结果。

于 2012-07-19T04:06:46.990 回答
-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;
    }
}

虽然硬编码的字符串数组不会存在很长时间,但直到我找出需要传入的数据类型,这个类就可以很好地解决问题。

于 2012-07-19T16:53:11.217 回答