我想修改加载JAXB的对象(来自XML),以便我可以用更新的XML将它们编组回磁盘。
现在举个例子:
<Customers>
<Customer id="1" name="Jack">
<Address type="Residence">
<FirstLine>1 saxon Court</FirstLine>
<City>CY</City>
</Address>
</Customer>
<Customer id="2" name="Iain">
<Address type="Residence">
<FirstLine>104 Bank Road</FirstLine>
<City>NY</City>
</Address>
</Customer>
</Customers>
现在由于我有多个客户,我想使用XPATH功能来获取Customer[@id=2]
对象的句柄,我可以在其中添加/更新地址。
如果我不使用类似XPATH的功能,那么JAXB生成的类将具有“L ist<Customer> customer
”,我将不得不遍历客户列表以匹配我想要的Customer[@id=2]
。
任何人都可以告诉我如何使用XPATH获取JAXB生成的对象的Object实例句柄,因此我可以将其编组以更新磁盘上的实际XML。 如果无法通过JAXB完成,那么可以使用具有XPATH灵活性的Java对象来读取和写入XML的替代解决方案。
使用示例代码更新了问题:
以下示例代码显示了我想用Moxy / JAXB实现的目标。
package org.soc.test.customers.moxy;
import java.io.File;
import java.util.List;
import javax.xml.bind.*;
public class UnmarshalDemo {
public static void main(String[] args) throws Exception {
org.eclipse.persistence.jaxb.JAXBContext jc = (org.eclipse.persistence.jaxb.JAXBContext) JAXBContext.newInstance(Customer.class);
File instanceDoc = new File("input.xml");
Customer customer = (Customer) jc.createUnmarshaller() .unmarshal(instanceDoc);
List<PhoneNumber> phones = jc.getValueByXPath(customer, "phone-number[@id=\"12\"]", null, List.class);
String customerId = jc.getValueByXPath(customer, "@id", null, String.class);
System.out.println("Customerid " + customerId + " , phone " + (phones==null?"0":phones.size()));
jc.setValueByXPath(customer, "phone-number[@id=\"12\"]/area-code/text()", null, "555");
jc.createMarshaller().marshal(customer, System.out);
}
}
输入XML:
<?xml version="1.0" encoding="UTF-8"?>
<customer id="1141">
<first-name>Jon</first-name>
<last-name>Smith</last-name>
<phone-number id="11">
<area-code>515</area-code>
<number>2726652</number>
</phone-number>
<phone-number id="12">
<area-code>515</area-code>
<number>2726652</number>
</phone-number>
</customer>
XSD:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="unqualified"
attributeFormDefault="unqualified">
<xs:element name="customer">
<xs:complexType>
<xs:sequence>
<xs:element name="first-name" type="stringMaxSize5"/>
<xs:element name="last-name" type="stringMaxSize5"/>
<xs:element ref="phone-number" maxOccurs="2"/>
</xs:sequence>
<xs:attribute name="id" type="xs:string"/>
</xs:complexType>
</xs:element>
<xs:element name="phone-number">
<xs:complexType>
<xs:sequence>
<xs:element name="area-code" type="stringMaxSize5"/>
<xs:element name="number" type="xs:string"/>
</xs:sequence>
<xs:attribute name="id" type="xs:string"/>
</xs:complexType>
</xs:element>
<xs:simpleType name="stringMaxSize5">
<xs:restriction base="xs:string">
<xs:maxLength value="5"/>
</xs:restriction>
</xs:simpleType>
</xs:schema>
jaxb.properties:
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
输出: Customerid 1141,电话0
我希望电话号码的列表大小为1,但它返回null。
希望这有助于理解我所面临的问题。
由于 Venkat
答案 0 :(得分:0)
Moxy不支持它。 org.eclipse.persistence.internal.oxm.Context
仅支持方括号中的数字索引。虽然XPathFragment
理解它并创建适当的谓词,但Context
会忽略搜索匹配的内容。我要么提出错误,要么寻找其他工具。
请参阅Context
源代码(提交7cedaac6cdf9384ae9a06129d6f9abd607f9e3c4
,第371行)以了解具体情况。