1

XSDから生成されたXmlBeansクラスがあります。永続化されたオブジェクトの行番号を追跡したいと思います。これは可能ですか?この情報が解析中に保存されるか(xml→beans)、またはプリティプリント中に保存されるか(beans→xml)は、アプリケーションフローで同期を維持するため、気にしません。

可能であれば、開始行と終了行/列の番号を教えてください。

ロケーターデータにアクセスするために、ある種の非標準のハックを使用する必要があるかどうかは気にしません。

XSDファイルからクラスを生成してロケーターデータをサポートできる別のJavaXMLフレームワークがある場合は、切り替えてもかまいません。

4

2 に答える 2

2

注: 私はEclipseLink JAXB(MOXy)のリーダーであり、JAXB(JSR-222)エキスパートグループのメンバーです。

XSDファイルからクラスを生成してロケーターデータをサポートできる別のJavaXMLフレームワークがある場合は、切り替えてもかまいません。

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 forum10241929.Customer@144aa0ce [2,11]
Start forum10241929.Address@19e3cd51 [4,14]
End forum10241929.Address@19e3cd51 [6,15]
End forum10241929.Customer@144aa0ce [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;
    }

}
于 2012-04-20T10:16:49.910 に答える
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();
        }
    }
}
于 2012-04-20T23:21:42.483 に答える