2012-04-20 10 views
1

我有從XSD生成的XmlBeans類。我想跟蹤持續對象的行號。這可能嗎?我不關心這些信息是在解析(xml→beans)期間還是在prettyprinting(beans→xml)期間存儲的,因爲我在應用程序流中將它們保持同步。XmlBeans在讀/寫過程中的源定位器

如果可能,我想開始和結束行/列號。

我不在乎是否必須使用某種非標準hack才能訪問定位器數據。

如果還有另一個Java XML框架可以從XSD文件支持定位器數據生成類,那麼我願意切換。

+0

你能用一個例子來說明你的問題嗎? – artbristol 2012-04-20 09:17:25

回答

1

只需使用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(); 
     } 
    } 
} 
+1

當然,但是如何訪問給定對象的行號? – 2012-04-22 01:14:09

+0

我已更新示例代碼,顯示如何檢索書籤。 – 2012-04-24 23:46:53

2

備註:我是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; 
    } 

} 
+0

謝謝你的回答。我將這個標記爲已回答,即使我已經實現了不同的解決方案,基於這裏的答案:http://stackoverflow.com/questions/4915422/get-line-number-from-xml-node-java 基本上,我首先解析爲一個常規的DOM樹,同時將位置信息保存爲用戶數據,然後將該DOM樹饋送給XmlBeans。這給了我正確的開始和結束信息。 – 2012-04-20 10:37:23

+0

這是一個可怕的XmlBeans比較... – 2012-04-20 23:19:10

+0

@KevinKrouse - 怎麼樣? – 2012-04-20 23:22:50