java JAXB具有XPATH灵活性,可在运行时修改对象
我想修改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生成的类将具有“List<Customer> customer
”,并且我必须遍历客户列表以匹配我想要的Customer[@id=2]
有谁能告诉我如何使用XPATH获取JAXB生成的对象的对象实例句柄,这样我就可以重新整理它来更新磁盘上的实际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。特性:
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
输出: Customerid 1141,电话0
我希望电话号码的列表大小为1,但它返回null
希望这有助于理解我所面临的问题
谢谢 文卡特
# 1 楼答案
莫西不支持它。
org.eclipse.persistence.internal.oxm.Context
只支持方括号中的数字索引。虽然XPathFragment
理解它并创建适当的谓词,但Context
在搜索匹配项时会忽略这些谓词。我要么提出一个错误,要么寻找另一个工具请参阅^{} 源代码(Commit
7cedaac6cdf9384ae9a06129d6f9abd607f9e3c4
,第371行之后),以了解发生了什么