2012-04-20 3 views
1

У меня есть классы XmlBeans, созданные из XSD. Я хотел бы отслеживать номера строк для сохраняемых объектов. Это возможно? Меня не волнует, сохраняется ли эта информация во время разбора (xml → beans) или во время красивой печати (beans → xml), потому что я держу их в синхронизации в потоке приложения.XmlBeans локатор источника во время чтения/записи

Я хотел бы указать начальную и конечную строки/номера столбцов, если это возможно.

Меня не волнует, если мне нужно использовать какой-то нестандартный хак, чтобы получить данные локатора.

Если есть еще одна инфраструктура Java XML, которая может генерировать классы из файла XSD и, то я хочу переключиться.

+0

Можете ли вы уточнить свой вопрос на примере? – artbristol

ответ

1

Просто используйте XmlOptions#setLoadLineNumbers(), например:

MyDocument.Factory.parse(xmlFile, new XmlOptions().setLoadLineNubmers()); 

Затем, чтобы получить номера строк из XML Store, найти ближайший 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

Уверен, но тогда как бы вы получили доступ к номеру строки для данного объекта? –

+0

Я обновил образец кода, показывающий, как получить закладки. –

2

Примечание: Я - лидер EclipseLink JAXB (MOXy) и входит в группу экспертов JAXB (JSR-222).

Если есть другая структура Java XML, который может генерировать классы из данных в формате XSD файлов и поддержка локатора, то я готов переключиться.

JAXB может генерировать классы из схемы XML, а ниже - несколько способов получить информацию о местоположении. Для сравнения JAXB и XMLBeans см:

ВАРИАНТ # 1 - StAX и Unmarshaller.Listener

Demo

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

Существует расширение JAXB, который поддерживается как EclipseLink JAXB (Moxy) и эталонная реализация называется @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. Это дает мне правильную начальную и конечную информацию. –

+0

Это ужасное сравнение с XmlBeans ... –

+0

@KevinKrouse - Как так? –

Смежные вопросы