有没有一种方法可以通过SAX/DOM解析每个节点可用的行号

问题描述:

我已经为包含大量可用于自动生成Java代码的项目的大型XML文档格式编写了DOM解析器。这仅限于小型表达式,然后将其合并到动态生成的Java源文件中。有没有一种方法可以通过SAX/DOM解析每个节点可用的行号

到目前为止 - 太好了。一切正常。

但我希望能够嵌入包含Java代码的XML节点的行号(这样如果配置包含不可编译的代码,每个方法都会有一个指向源XML文档的指针和线号以方便调试)。我不需要解析时的行号,也不需要验证XML源文档并在特定的行号处发生错误。我需要能够访问我的DOM中的每个节点和属性的行号或每个SAX事件。

关于我如何能够实现这一点的任何建议?

P.S. 此外,我读StAX有一个方法来解析时获取行号,但理想情况下,我希望在Java 4/5中使用常规SAX/DOM处理实现相同的结果,而不是成为Java 6+应用程序或采取额外.jar文件。

也许与org.xml.sax.Locator

+0

太好了,我会检查出来。我问了这个问题,因为我似乎已经消耗了一些错误信息,声称在1.4/5.0的默认SAX处理器中这是不可能的。如果我有成功,我会在这里报告。 – Chris 2010-05-09 17:52:20

+0

谢谢,正是我在寻找的。 – jutky 2011-11-02 11:39:51

我知道这个线程是有点老了(对不起),但它已经采取了这么长时间才破解这个螺母,我不得不与别人分享的解决方案...

你只能似乎能够获得没有构建DOM的SAX的行号。 DOM解析器不会提供行号,也不会让您靠近它正在使用的SAX解析器。我的解决方案是使用SAX源和DOM结果进行空的XSLT转换,但即使如此,仍有人尽其所能隐藏了这一点。请参阅下面的代码。

我将位置信息添加到每个元素作为属性与我自己的名称空间,所以我可以使用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); 
    } 
} 
+0

感谢您的信息。 – Chris 2011-02-17 01:40:51

+0

绝对必要,清晰简洁。我知道这必须存在 – albfan 2012-01-12 03:54:56