让具有属性的XML节点的子节点 - Java

时间:2014-11-19 08:04:24

标签: java xml parsing

我有一个XML文件,其中包含许多具有属性的节点以及具有相同字段名称的子元素:

<doc>
    <str name="eventId">54605a22aa7d649f085242e3</str>
    <arr name="toolLogExt">
      <str>.xls.lck</str>
      <str>.xls.lck</str>
      <str>.xls.lck</str>
    </arr>
    <arr name="messageTech">
      <str>Java run-time error</str>
      <str>Java run-time error</str>
      <str>Java run-time error</str>
    </arr>
    <arr name="messageId">
      <str>546066238d194b463e365194</str>
      <str>546090b48d194b463e365196</str>
      <str>546090f78d194b463e365198</str>
    </arr>
    <arr name="eventType">
      <str>Run-time error</str>
    </arr>
    <str name="type">acme</str>
    <arr name="messageSolution">
      <str>XXXXX</str>
      <str>YYYYY</str>
      <str>ZZZZZ</str>
    </arr>
    <arr name="toolID">
      <str>54605d7d8d194b463e36517e</str>
      <str>54605d7d8d194b463e36517e</str>
      <str>54605d7d8d194b463e36517e</str>
    </arr>
</doc>

我已经阅读了很多关于Stack-Overflow的帖子,但我还没有像这样在XML格式中出现过。常规方法之一是在获得具有各自属性的每个节点之后进行单独的字符串处理,并保持计数以便稍后构建文档模型。但是,是否有直接获取所有字段的方法?

EDIT1 到目前为止我的方法......

import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.w3c.dom.Document;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class ParseSAX extends DefaultHandler {
    List<String> errorsLister;
    String inpXMLFileName;
    public ParseSAX(String xmlFileName) {
        this.inpXMLFileName = xmlFileName;
        errorsLister = new ArrayList<String>();
        parseDocument();
    }
    private void parseDocument() {
        // parse
        SAXParserFactory factory = SAXParserFactory.newInstance();
        try {
            SAXParser parser = factory.newSAXParser();
            parser.parse(inpXMLFileName, this);
        } catch (ParserConfigurationException e) {
            System.out.println("ParserConfig error");
        } catch (SAXException e) {
            System.out.println("SAXException : xml not well formed");
        } catch (IOException e) {
            System.out.println("IO error");
        }
    }

    @Override
    public void startElement(String s, String s1, String elementName, Attributes attributes) throws SAXException {

        if (elementName.equalsIgnoreCase("str")) {
            String temp = (attributes.getValue("eventId"));
            // This would give me the event ID
            // Further usage
        }
        // if current element is publisher
        if (elementName.equalsIgnoreCase("arr")) {
           String temp = attributes.getValue("messageTech");
        }
    }
    @Override
    public void endElement(String s, String s1, String element) throws SAXException {
        // Can't seem to figure out what to do here!!!
    }

    public static void main(String[] args) {
        new ParseSAX("..//input2.xml");

        // To individually get field values having attribute names
        // I know we can do this .... 
        /**
        try {
            DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = domFactory.newDocumentBuilder();
            Document dDoc;
            dDoc = builder.parse("..//input2.xml");
            XPath xPath = XPathFactory.newInstance().newXPath();
            String string = (String) xPath.evaluate("/response/result[@name='response']/doc/arr[@name='messageId']/str", dDoc, XPathConstants.STRING);
        } catch (SAXException | IOException | XPathExpressionException | ParserConfigurationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        **/
    }
}

1 个答案:

答案 0 :(得分:2)

您可以使用以下函数读取任何XML标记内的元素。

public class XmlFileReader{
    public NodeList readXML(String filePath, String tagName, String subTagName, String tagAttr) {
        try {
            // Get XML file object.
            File fXmlFile = new File(filePath);

            DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
            Document doc = dBuilder.parse(fXmlFile);

            doc.getDocumentElement().normalize();

            System.out.println("Root element :" + doc.getDocumentElement().getNodeName());

            NodeList nodeList = doc.getElementsByTagName(tagName);

            for (int i = 0; i < nodeList.getLength(); i++) {
                Node node = nodeList.item(i);
                if (node.getNodeType() == Node.ELEMENT_NODE) {
                    Element element = (Element) node;
                    if (element.getAttribute("name").equalsIgnoreCase(tagAttr)) {
                        NodeList elementsByTagName = element.getElementsByTagName(subTagName);
                        return elementsByTagName ;
                    }
                }
            }
        } catch (Exception e) {
            StringWriter stack = new StringWriter();
            e.printStackTrace(new PrintWriter(stack));
            LogManager.fatal(stack.toString(), ReadTemplate.class.getName());
        }
        return elementsByTagName;
    }
}

功能调用:

XmlFileReader xmlFileReader = new XmlFileReader();
NodeList toolLogExtChilds = xmlFileReader.readXML("Path to XML file",
                "arr", "str", "toolLogExt");