使用Java中的XPath和Saxon获取源文档中的行号,而不是转换后的文档中的行号

时间:2018-09-20 03:36:04

标签: java xml xpath xml-parsing saxon

有什么方法可以在Java中使用Saxon来返回源文档中匹配元素的行号? 例如,我有以下XML

<property name="random name" value="
        -firstSentence=false
        -secondSentence=true
        -thirdSentence=true" />

我对原始文档中的第三行感兴趣。我使用了以下XPath:

/property[matches(@value, '^.*secondSentence=true.*$')]

然后在Saxon的XdmNode中调用getLineNumber,它返回给我第2行 我发现使用DocumentBuilder解析为XdmNode时XML文档的原始格式已消失

它返回以下格式的xml并在其上运行XPath

<property name="random name"
      value="                          -firstSentence=false                          -secondSentence=true                         -thirdSentence=true"/>

其中将值数据限制在一行中,这是XPath在其上运行并返回行号的行

我想知道Saxon是否有可能无法自动格式化XML文档并对其处理XPath规则,以使从XdmNode返回的行号反映原始文档中的确切行?

或者如果您知道任何XML解析库/ XPath也可以做到这一点?

1 个答案:

答案 0 :(得分:0)

在Saxon中打开行号时,它将保留XML解析器报告的行号。对于SAX解析器,为每个SAX事件报告的行号表示产生该事件的构造结尾在源文件中的位置。属性是作为startElement()事件的一部分报告的,因此,我们最好的办法是报告出现在开始标记末尾的“>”字符的位置。

这实际上与“属性值规范化”无关,该过程是XML解析器应用于属性值的过程,导致换行符和制表符被空格替换。 (这两个问题唯一的共同点是,在两种情况下,XML解析器都遵循规则,而Saxon无法告诉它这样做。)

如果您真的想解决此问题,则可能必须执行类似于oXygen(我相信)做的事情:它使用Saxon报告的行号和列号作为开始标签的结尾,然后读取在源文件中从那里返回,以找到相关属性的位置,以便它可以通过在带下划线的地方标出红色来标记违规属性。

或者,有可能(可能值得研究)是否可以从Stax解析器(如Woodstox或Aalto)获得更细粒度的位置信息,其中每个属性都作为单独的事件进行通知。如果是这种情况,那么尽管Saxon无法记录属性级别的位置信息,但是您可以通过其他方式将其传递,例如,通过将自定义NodeFactory与链接树模型一起使用,将信息放入以下内容的子类中:元素的标准ElementImpl表示形式。