我正在尝试编写一个通用的xml解析器来解析所有xml标记,并将数据及其值作为键值对获取到地图中。 示例xml:
<?xml version="1.0"?>
<company>
<staff>
<firstname>Kevin</firstname>
<lastname>Gay</lastname>
<salary>50000</salary>
</staff>
</company>
输出如下: NodeName:[公司]价值:[
Kevin
Gay
50000
]
NodeName:[staff] Value:[
Kevin
Gay
50000
]
NodeName:[firstname] Value:[Kevin]
NodeName:[lastname] Value:[Gay]
NodeName:[salary] Value:[50000]
我的代码如下:
final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
final DocumentBuilder db = dbf.newDocumentBuilder();
final ByteArrayInputStream bis = new ByteArrayInputStream(xmlString.getBytes());
//where xmlString is a file read using DataInputStream.
final Document doc1 = db.parse(bis);
printElements(doc1);
void printElements(final Document doc)
{
final NodeList nl = doc.getElementsByTagName("*");
Node node;
for (int i = 0; i < nl.getLength(); i++)
{
node = nl.item(i);
System.out.println("NodeName:[" + node.getNodeName() + "] Value:[" + node.getTextContent() + "]");
}
}
如何从打印中消除员工和公司属性。 我不想按标签名称使用JAXB或getTags,因为xml标签数据每次都会更改,我正在编写通用的xml解析器,其工作是解析标签及其值并将其放入映射中。
Alo如何找到我正在解析的标签的父级,以便我可以跟踪孩子来自哪里,在这种情况下......公司0-&gt; staff-&gt; firstname。
答案 0 :(得分:1)
可以通过以下更改来实现:
for (int i=0; i<nodeList.getLength(); i++)
{
// Get element
Element element = (Element)nodeList.item(i);
final NodeList nodes = element.getChildNodes();
if(nodes.getLength() == 1)
{
System.out.println(element.getNodeName() + " " + element.getTextContent());
}
}
答案 1 :(得分:0)
JaxB将是一个更好的类,但你可以尝试这样简单的东西:
for (int i = 0; i < nl.getLength(); i++)
{
node = nl.item(i);
//check to see if node's name is what you don't want it to be
if(node.getNodeName().equals("Staff") || node.getNodeName().equals("Comapny"))
{
//do stuff or dont do anything...
}
else//print other stuff
{
System.out.println("NodeName:[" + node.getNodeName() + "] Value:[" + node.getTextContent() + "]");
}
}
就您的第二个问题而言,我建议您查看Node API:
http://docs.oracle.com/javase/6/docs/api/org/w3c/dom/Node.html
提示:getParentNode()
如果您想要父级的最深层部分(名字,姓氏,工资),您可以获得第一个节点。然后执行node.getChildNodes()以获取子节点列表。彻底搜索每个孩子,直到你找到一个没有孩子的孩子。然后你知道这是一个叶子节点。你想打印它。
答案 2 :(得分:0)
您可以使用SAX解析器来解析XML并编写自己的处理程序来扩展DefaultHandler。
跟踪您在堆栈中读取的标记,并存储在调用字符()时读取的字符。调用endElement()时,从堆栈中弹出顶部标记,这是标记名称,而字符()读入的最后一个值是此标记的值。堆栈中剩下的字符串是导致此标记的父标记,例如
对于读取XML文件的主方法:
public static void main(String[] args) {
File xmlFile = new File("somefile.xml");
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser saxParser = factory.newSAXParser();
MyHandler handler = new MyHandler();
saxParser.parse(xmlFile, handler);
Map<String, String> map = handler.getDataMap();
}
我们有自己的处理程序。
public class MyHandler extends DefaultHandler {
private String characters = null;
private Stack<String> tagStack;
private Map<String, String> dataMap;
public MyHandler() {
this.tagStack = new Stack<String>();
this.dataMap = new HashMap<String, String>();
}
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
this.tagStack.push(qName);
}
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
// trimming to take out whitespace between tags
characters = new String(ch).trim();
}
@Override
public void endElement(String uri, String localName,
String qName) throws SAXException {
// check that the end element we're looking at matches the last read
// startElement this should only happen if we don't have well-formed XML
if (qName.equals(this.tagStack.peek())) {
String[] tagArray = this.tagStack.toArray(new String[this.tagStack.size()]);
// make use of apache-common-lang, or write your own code to concat
// the list with '.'s
String tagHierarchy = StringUtils.join(tagArray, ".");
this.dataMap.put(tagHierarchy, this.characters);
// EDIT: I forgot to pop the last item off the stack :)
this.tagStack.pop();
} else {
throw new SAXException("XML is not well-formed");
}
}
public Map<String, String> getDataMap() {
return this.dataMap;
}
}
这将返回一个Map,其中使用OP中描述的输入数据:
["company.staff.firstname", "Kevin"]
["company.staff.lastname", "Gay"]
["company.staff.salary", "50000"]
如果您不想要元素的完整路径作为键,例如Map,其中key是标记名称,并且值[0]是父路径和值[1],则可以进行自己的调整。 ]是实际值等。