获取具有属性的XML节点的子节点-Java

获取具有属性的XML节点的子节点-Java,java,xml,parsing,Java,Xml,Parsing,我有一个XML文件,其中有许多具有属性的节点以及具有相同字段名的子元素: <doc> <str name="eventId">54605a22aa7d649f085242e3</str> <arr name="toolLogExt"> <str>.xls.lck</str> <str>.xls.lck</str> <str>.xls.lc

我有一个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>

54605a22aa7d649f085242e3
.xls.lck
.xls.lck
.xls.lck
Java运行时错误
Java运行时错误
Java运行时错误
546066238d194b463e365194
546090b48d194b463e365196
546090f78d194b463e365198
运行时错误
顶点
XXXXX
YYYY
ZZZZZ
54605d7d8d194b463e36517e
54605d7d8d194b463e36517e
54605d7d8d194b463e36517e
我读过很多关于堆栈溢出的文章,但我还没有找到像这样的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();
        }
        **/
    }
}
import java.io.IOException;
导入java.text.ParseException;
导入java.text.simpleDataFormat;
导入java.util.ArrayList;
导入java.util.List;
导入javax.xml.parsers.DocumentBuilder;
导入javax.xml.parsers.DocumentBuilderFactory;
导入javax.xml.parsers.parserConfiguration异常;
导入javax.xml.parsers.SAXParser;
导入javax.xml.parsers.SAXParserFactory;
导入javax.xml.xpath.xpath;
导入javax.xml.xpath.XPathConstants;
导入javax.xml.xpath.XPathExpressionException;
导入javax.xml.xpath.XPathFactory;
导入org.w3c.dom.Document;
导入org.xml.sax.Attributes;
导入org.xml.sax.SAXException;
导入org.xml.sax.helpers.DefaultHandler;
公共类ParseSAX扩展了DefaultHandler{
列表错误slister;
字符串文件名;
公共解析SAX(字符串xmlFileName){
this.inpXMLFileName=xmlFileName;
errorsLister=新的ArrayList();
解析文档();
}
私有文档(){
//解析
SAXParserFactory=SAXParserFactory.newInstance();
试一试{
SAXParser parser=factory.newSAXParser();
parse(inpXMLFileName,this);
}捕获(ParserConfiguration异常e){
System.out.println(“ParserConfig错误”);
}捕获(SAXE异常){
System.out.println(“SAXException:xml格式不正确”);
}捕获(IOE异常){
System.out.println(“IO错误”);
}
}
@凌驾
public void startElement(字符串s、字符串s1、字符串elementName、属性)引发SAXException{
if(elementName.equalsIgnoreCase(“str”)){
字符串temp=(attributes.getValue(“eventId”);
//这将为我提供事件ID
//进一步使用
}
//如果当前元素是publisher
if(elementName.equalsIgnoreCase(“arr”)){
字符串temp=attributes.getValue(“messageTech”);
}
}
@凌驾
公共void endElement(字符串s、字符串s1、字符串元素)引发SAXException{
//似乎不知道该在这里做什么!!!
}
公共静态void main(字符串[]args){
新的ParseSAX(“../input2.xml”);
//单独获取具有属性名称的字段值的步骤
//我知道我们可以做到。。。。
/**
试一试{
DocumentBuilderFactory domFactory=DocumentBuilderFactory.newInstance();
DocumentBuilder=domFactory.newDocumentBuilder();
文件dDoc;
dDoc=builder.parse(“../input2.xml”);
XPath=XPathFactory.newInstance().newXPath();
String String=(String)xPath.evaluate(“/response/result[@name='response']/doc/arr[@name='messageId']/str”,dDoc,XPathConstants.String);
}捕获(SAXException | IOException | XPathExpressionException | ParserConfiguration异常e){
//TODO自动生成的捕捉块
e、 printStackTrace();
}
**/
}
}

您可以使用下面的函数读取任何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;
    }
}

“字段名”是什么意思?到目前为止你试过什么?现在还不清楚问题是什么——获取属性值相当容易,获取元素的文本值也相当容易……假设我获取一个具有[@name='toolLogExt']的节点和属性。如何获取属于此节点的所有子节点,因为它们都具有字段?我现在正在编辑中发布我的代码片段。获取单个值甚至元素的文本值都很容易……但是我们如何获取所有子字段呢?属于此匹配节点?…并且所有子节点都具有相同的字段名——如上所述,您可以在XML文件中搜索
name
属性。一旦你得到了这个节点,就把它转换成
Element
type&然后使用
Element.getElementsByTagName(subTagName)
获取元素中的所有元素。看看我的答案。我希望它能帮助你。谢谢你的帮助!我正在尝试你的解决方案。你能用上面的答案得到解决方案吗?
XmlFileReader xmlFileReader = new XmlFileReader();
NodeList toolLogExtChilds = xmlFileReader.readXML("Path to XML file",
                "arr", "str", "toolLogExt");