Is there a way to parse XML through SAX / DOM with line numbers available behind node

I already wrote a DOM parser for a large XML document format that contains several elements that can be used to automatically generate Java code. This is limited to small expressions, which are then combined into a dynamically generated Java source file.

So far - so good. Everything is working.

BUT. I want to be able to embed the line number of the XML node where the Java code was included (so if the configuration contains incompressible code, each method will have a pointer to the source XML document and a line number for debugging convenience). I do not require a line number during parsing, and I do not need to check the source XML document and throw an error on a specific line number. I need to have access to the row number for each node and attribute in my DOM or in a SAX event.

Any suggestions on how I can achieve this?

PS In addition, I read that StAX has a method of getting the line number during parsing, but ideally I would like to achieve the same result with regular SAX / DOM processing in Java 4/5, and not become a Java 6+ application or take an extra . jar.

+3
2
+3

, (), , , -...

, SAX, DOM. DOM , SAX, . , XSLT SAX DOM, - , . . .

, XPath , .

, :

// The file to parse.
String systemId = "myxml.xml";

/*
 * Create transformer SAX source that adds current element position to
 * the element as attributes.
 */
XMLReader xmlReader = XMLReaderFactory.createXMLReader();
LocationFilter locationFilter = new LocationFilter(xmlReader);

InputSource inputSource = new InputSource(new FileReader(systemId));
// Do this so that XPath function document() can take relative URI.
inputSource.setSystemId(systemId);
SAXSource saxSource = new SAXSource(locationFilter, inputSource);

/*
 * Perform an empty transformation from SAX source to DOM result.
 */
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMResult domResult = new DOMResult();
transformer.transform(saxSource, domResult);
Node root = domResult.getNode();

...
class LocationFilter extends XMLFilterImpl {

    LocationFilter(XMLReader xmlReader) {
        super(xmlReader);
    }

    private Locator locator = null;

    @Override
    public void setDocumentLocator(Locator locator) {
        super.setDocumentLocator(locator);
        this.locator = locator;
    }

    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {

        // Add extra attribute to elements to hold location
        String location = locator.getSystemId() + ':' + locator.getLineNumber() + ':' + locator.getColumnNumber();
        Attributes2Impl attrs = new Attributes2Impl(attributes);
        attrs.addAttribute("http://myNamespace", "location", "myns:location", "CDATA", location);
        super.startElement(uri, localName, qName, attrs);
    }
}
+6

Source: https://habr.com/ru/post/1744685/


All Articles