XmlSlurper: получение номера строки groovy.util.slurpersupport.NodeChild в исходном файле.

Я использую XmlSlurper для анализа XML-файла для обработки. Мне нужно найти номер строки некоторых критериев соответствия в файле.

Вот что у меня так далеко:

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

Теперь мне нужно найти соответствующий номер строки для каждого соответствующего "сервлета". Используя SaxParser, я бы сделал следующее:

node.getUserData(SaxParser.KEY_LINE_NO)

Как бы я выполнил ту же задачу на GpathResult в Groovy?

Большое спасибо, Майкл

2 ответа

Вы не можете сделать это напрямую, но вы можете украсить каждый элемент анализируемого DOM атрибутом номера строки.

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 MySlurper extends XmlSlurper {    
    public static final String LINE_NUM_ATTR = "_srmLineNum"
    Locator locator

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

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

    @Override
    public void startElement(String uri, String localName, String qName, Attributes attrs) throws SAXException {
        Attributes2Impl newAttrs = new Attributes2Impl(attrs);        
        newAttrs.addAttribute(uri, LINE_NUM_ATTR, LINE_NUM_ATTR, "ENTITY", "" + locator.getLineNumber());        
        super.startElement(uri, localName, qName, newAttrs);
    }
}

def text = '''
<root>
  <a>one!</a>
  <a>two!</a>
</root>'''

def root = new MySlurper().parseText(text)

root.a.each { println it.@_srmLineNum }

Вот небольшая модификация предложения @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);
  }
}
Другие вопросы по тегам