XmlSlurper:获取原始文件中groovy.util.slurpersupport.NodeChild的行号

时间:2015-07-06 08:54:00

标签: groovy xmlslurper

我正在使用XmlSlurper来解析XML文件以进行处理。 我需要在文件中找到一些匹配条件的行号。

这是我到目前为止所做的:

  def void findServlets() {
    this.servlets = webFile.depthFirst().findAll{
      it.name() == 'servlet'
    }
    println this.servlets
  }

现在我需要找到每个匹配的' servlet的相关行号。 使用SaxParser,我会做以下事情:

node.getUserData(SaxParser.KEY_LINE_NO)

我如何在groovy中的GpathResult上完成相同的任务?

非常感谢, 迈克尔

2 个答案:

答案 0 :(得分:2)

您无法直接执行此操作,但您可以使用行号属性修饰已解析DOM的每个元素。

typings install packageName --ambient --save

答案 1 :(得分:1)

这是对@ preetham建议的略微修改。这允许您在XML

中设置开始和结束行号
import org.xml.sax.Attributes;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.ext.Attributes2Impl;
import javax.xml.parsers.ParserConfigurationException;

class NumberedXmlParser extends XmlSlurper {
  public static final String START_LINE = "_start"
  public static final String END_LINE = "_end"
  Locator locator
  // stack and parent are normally private variables in XmlParser
  // We create local references to these so that we can hook into them
  List<Node> localStack = new ArrayList<Node>();
  Node localParent;

  public NumberedXmlParser() throws ParserConfigurationException, SAXException {
    super();
  }

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

  @Override
  public void startDocument() throws SAXException {
    localParent = null;
    super.startDocument();
  }

  @Override
  public void endDocument() throws SAXException {
    localStack.clear();
    super.endDocument();
  }

  @Override
  public Node createNode(Node parent, Object name, Map attributes) {
    // Hack into this method to get access to the parent Node and stack
    this.localParent = new Node(parent, name, attributes);
    this.localParent["@$START_LINE"] = locator.getLineNumber();
    this.localStack.add(this.localParent);
    return this.localParent;
  }

  @Override
  public void endElement(final String uri, final String localName, final String qName) {
    if (!localStack.isEmpty()) {
      Node element = localStack.remove(localStack.size() - 1);
      element["@$END_LINE"] = locator.getLineNumber();
      if (!localStack.isEmpty()) {
        localParent = localStack.get(localStack.size() - 1);
      }
    }
    super.endElement(uri, localName, qName);
  }
}