Search code examples
javaxmlserializationxmlbeans

XmlBeans source locator during reading/writing


I have XmlBeans classes generated from an XSD. I would like to track line numbers for the persisted objects. Is this possible? I don't care if this information is stored during parsing (xml → beans) or during prettyprinting (beans → xml) because I keep them in synch in my application flow.

I would like start and end line/column numbers, if possible.

I don't care if I have to use some kind of non-standard hack to get to the locator data.

If there is another Java XML framework that can generate classes from an XSD file and support locator data, then I'm willing to switch.


Solution

  • Just use XmlOptions#setLoadLineNumbers(), for example:

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

    Then to retrieve the line numbers from the xml store, find the nearest XmlLineNumber bookmark.

    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();
            }
        }
    }