我有從XSD生成的XmlBeans類。我想跟蹤持續對象的行號。這可能嗎?我不關心這些信息是在解析(xml→beans)期間還是在prettyprinting(beans→xml)期間存儲的,因爲我在應用程序流中將它們保持同步。XmlBeans在讀/寫過程中的源定位器
如果可能,我想開始和結束行/列號。
我不在乎是否必須使用某種非標準hack才能訪問定位器數據。
如果還有另一個Java XML框架可以從XSD文件和支持定位器數據生成類,那麼我願意切換。
我有從XSD生成的XmlBeans類。我想跟蹤持續對象的行號。這可能嗎?我不關心這些信息是在解析(xml→beans)期間還是在prettyprinting(beans→xml)期間存儲的,因爲我在應用程序流中將它們保持同步。XmlBeans在讀/寫過程中的源定位器
如果可能,我想開始和結束行/列號。
我不在乎是否必須使用某種非標準hack才能訪問定位器數據。
如果還有另一個Java XML框架可以從XSD文件和支持定位器數據生成類,那麼我願意切換。
只需使用XmlOptions#setLoadLineNumbers(),例如:
MyDocument.Factory.parse(xmlFile, new XmlOptions().setLoadLineNubmers());
然後從XML存儲檢索行號,找到最近的XmlLineNumber書籤。
import org.apache.xmlbeans.*;
public class linenumber
{
public static void main(String[] args) throws XmlException
{
XmlOptions options = new XmlOptions().setLoadLineNumbers();
XmlObject xobj = XmlObject.Factory.parse("<a>\n<b>test</b>\n<c>test</c>\n</a>", options);
// let's get the line number for the '<c>' xml object
XmlObject cobj = xobj.selectPath(".//c")[0];
System.out.println(cobj.xmlText());
XmlCursor c = null;
try
{
c = cobj.newCursor();
// search for XmlLineNumber bookmark
XmlLineNumber ln =
(XmlLineNumber) c.getBookmark(XmlLineNumber.class);
if (ln == null)
ln = (XmlLineNumber) c.toPrevBookmark(XmlLineNumber.class);
if (ln != null)
{
int line = ln.getLine();
int column = ln.getColumn();
int offset = ln.getOffset();
System.out.println("line=" + line + ", col=" + column + ", offset=" + offset);
}
}
finally
{
if (c != null) c.dispose();
}
}
}
當然,但是如何訪問給定對象的行號? – 2012-04-22 01:14:09
我已更新示例代碼,顯示如何檢索書籤。 – 2012-04-24 23:46:53
備註:我是EclipseLink JAXB (MOXy)的領導者和JAXB (JSR-222)專家組的成員。
如果有另一個Java XML框架,可以從 生成類XSD文件,並支持定位數據,那麼我願意切換。
JAXB可以從XML模式生成類,下面介紹幾種獲取位置信息的方法。對於JAXB和XMLBeans的的比較看:
選項1 - StAX的和的Unmarshaller.Listener
演示
package forum10241929;
import java.io.File;
import javax.xml.bind.*;
import javax.xml.stream.*;
import javax.xml.transform.stream.StreamSource;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Customer.class);
XMLInputFactory xif = XMLInputFactory.newFactory();
XMLStreamReader xsr = xif.createXMLStreamReader(new StreamSource(new File("src/forum10241929/input.xml")));
Unmarshaller unmarshaller = jc.createUnmarshaller();
unmarshaller.setListener(new LocationListener(xsr));
Customer customer = (Customer) unmarshaller.unmarshal(xsr);
}
private static class LocationListener extends Unmarshaller.Listener {
private XMLStreamReader xsr;
public LocationListener(XMLStreamReader xsr) {
this.xsr = xsr;
}
@Override
public void afterUnmarshal(Object target, Object parent) {
log("End", target);
}
@Override
public void beforeUnmarshal(Object target, Object parent) {
log("Start", target);
}
private void log(String event, Object target) {
System.out.print(event);
System.out.print(" ");
System.out.print(target);
System.out.print(" [");
Location location = xsr.getLocation();
System.out.print(location.getLineNumber());
System.out.print(",");
System.out.print(location.getColumnNumber());
System.out.println("]");
}
}
}
input.xml中
<?xml version="1.0" encoding="UTF-8"?>
<customer>
<name>Jane Doe</name>
<address>
<street>1 A Street</street>
</address>
</customer>
輸出
Start [email protected] [2,11]
Start [email protected] [4,14]
End [email protected] [6,15]
End [email protected] [7,12]
顧客
package forum10241929;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class Customer {
private String name;
private Address address;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
}
地址
package forum10241929;
public class Address {
private String street;
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
}
選項#2 - @XmlLocation
有是受兩者的EclipseLink JAXB(MOXY)支撐的JAXB延伸和參考實現稱爲@XmlLocation
(下面是一個使用MOXy的示例)。這隻會捕獲開始位置。
package forum10241929;
import javax.xml.bind.annotation.XmlRootElement;
import org.eclipse.persistence.oxm.annotations.XmlLocation;
import org.xml.sax.Locator;
@XmlRootElement
public class Customer {
private String name;
private Address address;
@XmlLocation
private Locator location;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
}
謝謝你的回答。我將這個標記爲已回答,即使我已經實現了不同的解決方案,基於這裏的答案:http://stackoverflow.com/questions/4915422/get-line-number-from-xml-node-java 基本上,我首先解析爲一個常規的DOM樹,同時將位置信息保存爲用戶數據,然後將該DOM樹饋送給XmlBeans。這給了我正確的開始和結束信息。 – 2012-04-20 10:37:23
這是一個可怕的XmlBeans比較... – 2012-04-20 23:19:10
@KevinKrouse - 怎麼樣? – 2012-04-20 23:22:50
你能用一個例子來說明你的問題嗎? – artbristol 2012-04-20 09:17:25