Найти значение определенного атрибута в XML-файле на java

#java #xml

#java #xml

Вопрос:

Мне нужно просто прочитать значение одного атрибута внутри XML-файла, используя java. XML будет выглядеть примерно так:

 <behavior name="Fred" version="2.0" ....>
  

и мне просто нужно прочитать версию. Может ли кто-нибудь указать направление ресурса, который показал бы мне, как это сделать?

Комментарии:

1. Это хороший пример того, почему простые вещи не всегда выполняются легко. Несмотря на то, что большинство фреймворков Java в значительной степени полагаются на XML, инструменты, доступные для реальной работы с XML в Java, довольно громоздки.

Ответ №1:

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

 import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathFactory;

import org.w3c.dom.Document;

public class GetVersion {
    public static void main(String[] args) throws Exception {
        XPath xpath = XPathFactory.newInstance().newXPath();
        Document doc = DocumentBuilderFactory.newInstance()
            .newDocumentBuilder().parse("file:////tmp/whatever.xml");
        String version = xpath.evaluate("//behavior/@version", doc);
        System.out.println(version);
    }
}
  

Ответ №2:

JAXB для краткости:

   private static String readVersion(File file) {
    @XmlRootElement class Behavior {
      @XmlAttribute String version;
    }
    return JAXB.unmarshal(file, Behavior.class).version;
  }
  

StAX для повышения эффективности:

   private static String readVersionEfficient(File file)
      throws XMLStreamException, IOException {
    XMLInputFactory inFactory = XMLInputFactory.newInstance();
    XMLStreamReader xmlReader = inFactory
        .createXMLStreamReader(new StreamSource(file));
    try {
      while (xmlReader.hasNext()) {
        if (xmlReader.next() == XMLStreamConstants.START_ELEMENT) {
          if (xmlReader.getLocalName().equals("behavior")) {
            return xmlReader.getAttributeValue(null, "version");
          } else {
            throw new IOException("Invalid file");
          }
        }
      }
      throw new IOException("Invalid file");
    } finally {
      xmlReader.close();
    }
  }
  

Комментарии:

1. Эта версия JAXB довольно тревожна с точки зрения накладных расходов. 🙂

Ответ №3:

Вот один из них.

 import javax.xml.parsers.SAXParser;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.SAXException;
import org.xml.sax.Attributes;
import javax.xml.parsers.SAXParserFactory;

/**
 * Here is sample of reading attributes of a given XML element.
 */

public class SampleOfReadingAttributes {
    /**
     * Application entry point
     * @param args command-line arguments
     */
    public static void main(String[] args) {
        try {
            // creates and returns new instance of SAX-implementation:
            SAXParserFactory factory = SAXParserFactory.newInstance();

            // create SAX-parser...
            SAXParser parser = factory.newSAXParser();
            // .. define our handler:
            SaxHandler handler = new SaxHandler();

            // and parse:
            parser.parse("sample.xml", handler);

        } catch (Exception ex) {
            ex.printStackTrace(System.out);
        }
    }

    /**
     * Our own implementation of SAX handler reading
     * a purchase-order data.
     */
    private static final class SaxHandler extends DefaultHandler {

        // we enter to element 'qName':
        public void startElement(String uri, String localName,
                String qName, Attributes attrs) throws SAXException {

            if (qName.equals("behavior")) {
                // get version
                String version = attrs.getValue("version");


                System.out.println("Version is "   version );

            }
        }
    }
}
  

Комментарии:

1. Я бы использовал этот подход, если бы работал на JSE5, но javax.xml.stream API в Java 6 и JEE позволяет завершить синтаксический анализ после первого элемента, не прибегая к искусственным механизмам, таким как выдача исключения.

2. Боже, это сложно. Создание SAXParserFactory, SAXParser и пользовательского SaxHandler только для выполнения «//behavior» — это большая работа.

Ответ №4:

Как уже упоминалось, вы можете использовать SAXParser.

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

Вы также можете использовать XPath, который является языком для запроса xml. Это то, что я бы рекомендовал.

Ответ №5:

Если все, что вам нужно, это прочитать версию, то вы можете использовать regex. Но на самом деле, я думаю, вам нужен apache digester

Комментарии:

1. XML regext = flame bait 🙂 Но я согласен с вашей рекомендацией apache digester.

Ответ №6:

Конфигурация Apache Commons тоже хороша. На нем основан Commons Digester.