我正在尝试构建一个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>
元素。有什么建议吗?
答案 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数组不会存在很长时间,但直到我找到需要传递的数据类型,这个类才能正常工作。