有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

jaxb如何将带有内联模式的XML字符串处理为java对象?

我打电话给WCF。Net服务从Java代理。结果是一个具有内联模式的xml字符串(在流中)。我想使用JAXB将xml中的值解组到Java类。xml字符串如下所示:

<NewDataSet>
  <xs:schema id="NewDataSet" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
    <xs:element name="NewDataSet" msdata:IsDataSet="true" msdata:Locale="">
      <xs:complexType>
        <xs:choice minOccurs="0" maxOccurs="unbounded">
          <xs:element name="Table">
            <xs:complexType>
              <xs:sequence>
                <xs:element name="CustomerID" type="xs:int" minOccurs="0" />
                <xs:element name="CustomerNme" type="xs:string" minOccurs="0" />
              </xs:sequence>
            </xs:complexType>
          </xs:element>
        </xs:choice>
      </xs:complexType>
    </xs:element>
  </xs:schema>
  <Table>
    <CustomerID>1111</CustomerID>
    <CustomerNme>Customer One</CustomerNme>
  </Table>
  <Table>
    <CustomerID>2222</CustomerID>
    <CustomerNme>Customer Two</CustomerNme>
  </Table>
</NewDataSet>

由于基本结构将保持不变,我最初的想法是:

  1. 使用该模式可以使用xjc手动创建JAXB Java类
  2. 在处理过程中,使用嵌入的模式解析xml字符串,并丢弃模式和根节点NewDataSet
  3. 使用JAXB将字符串解组到java对象

有更好的方法吗

更新

尝试@Doughans方法。很近,但还没有雪茄。一个复杂的问题是xml被压缩了。下面的代码就是我要做的。我已经将Customer类成员设置为大写,以匹配确切的xml元素,但是对于解组操作的每个实例,我得到的都是null

//everything good to here...
JAXBElement<byte[]> byteRet = searchCustResponse.getSearchCustomersResult();
byte[] gzBytes = byteRet.getValue(); //these are gzipped bytes

//decompress...
ByteArrayInputStream bais = new ByteArrayInputStream(gzBytes);
GZIPInputStream gzipis = new GZIPInputStream(bais);
//InputStreamReader isr = new InputStreamReader(gzipis, "UTF-8");

//convert xml to string...
StringWriter writer = new StringWriter();
IOUtils.copy(gzipis, writer, "UTF-8");
String xmlString = writer.toString();

//read the string...
//StreamSource xml = new StreamSource(xmlString);
Reader reader = new StringReader(xmlString);

XMLInputFactory xif = XMLInputFactory.newFactory();
XMLStreamReader xsr = xif.createXMLStreamReader(reader);

List<WPTSCustomer> wptsCustomers = new ArrayList<WPTSCustomer>();

try {
    while (xsr.hasNext()) {
        int next = xsr.next();
        //xsr.nextTag();
        if (next == XMLStreamReader.START_ELEMENT) {
            if (xsr.getLocalName().equals("Table")) {
                JAXBContext jc = JAXBContext.newInstance(WPTSCustomer.class);
                Unmarshaller unmarshaller = jc.createUnmarshaller();
                JAXBElement<WPTSCustomer> jb = unmarshaller.unmarshal(xsr, WPTSCustomer.class);
                WPTSCustomer customer = jb.getValue();
                System.out.println(customer.getCustomerID()); //prints null
                System.out.println(customer.getCustomerNme()); //prints null
                wptsCustomers.add(customer);
            }
        }
    }
} finally {

StreamSource的使用对我不起作用。最后,我对xml字符串进行了遍历,直到它执行解组为止,而解组并没有填充对象

更新2

现在放弃JAXB。下面的代码工作得很好,我将把这些值放到我的POJO中。我确实尝试过从服务返回的完整xml字符串在JDev中创建一个XSD,然后从XSD中创建一个JAXB类。除了来自内联模式的名称冲突外,这几乎起到了作用。也许有办法解决这个问题

int eventType = xsr.getEventType();
while (xsr.hasNext()) {
    eventType = xsr.next();
    if (xsr.isStartElement() && xsr.getLocalName().equals("Table")) {
        xsr.nextTag();
        while (xsr.hasNext()) {
            if (xsr.isStartElement()) {
                if (xsr.getLocalName().equals("CustomerID")) {
                    System.out.println("id: " + xsr.getElementText());
                }
                if (xsr.getLocalName().equals("CustomerNme")) {
                    System.out.println("name: " + xsr.getElementText());
                }
            }
            xsr.next();
        }
    }

--


共 (2) 个答案

  1. # 2 楼答案

    对于可能再次遇到此问题的人,如果您尝试从xml字符串读取数据,则可能不起作用,但如果您可以在InputStream中获取数据,则可以将其传递给XMLStreamReader,这样就可以了。@Blaise的博客很棒

    我使用xjc选择手动创建Javaobject的模式,然后使用XMLStreamReader解析jax rs响应并获取输入流。如果成功,将尝试删除手动步骤并更新post

    XMLInputFactory xif = XMLInputFactory.newFactory();
    StreamSource xml = new StreamSource(httpResponse.getEntity().getContent());
    XMLStreamReader xsr = xif.createXMLStreamReader(xml);
    xsr.nextTag();
    while (!xsr.getLocalName().equals("GetAccountInfoResults")) {
        xsr.nextTag();
    }
    JAXBContext jc = JAXBContext.newInstance(GetAccountInfoResults.class);
    Unmarshaller unmarshaller = jc.createUnmarshaller();
    JAXBElement<GetAccountInfoResults> jb = unmarshaller.unmarshal(xsr, GetAccountInfoResults.class);
    xsr.close();
    
    GetAccountInfoResults result = jb.getValue();