大家都知道,Solr是一个基于Lucene高可配置的搜索服务器,大部分参数值以及相关优化等等都可以在solrconfig.xml中配置,那么就需要一个能够很快的进行解析和读取配置文件内容的数据结构,为此Solr提供了NamedList结构。
NamedList,一个有序的name/value容器,NamedList不像Map,他具有以下特点:
1、名字可以重复
2、NamedList中的element保持这有序状态
3、可以下标的形式访问Elements
4、name和value都可以为null
NamedList中通过下边访问要快于通过name访问。
NamedList在org.apache.solr.common.util包下面,把配置文件转换成NamedList需要另外两个辅助类DOMUtil和StrUtils, NamedList支持集中简单的数据类型,这个可以在DOMUtil的代码中可以看出,如下:
@SuppressWarnings("unchecked") public static void addToNamedList(Node nd, NamedList nlst, List arr) { // Nodes often include whitespace, etc... so just return if this // is not an Element. if (nd.getNodeType() != Node.ELEMENT_NODE) return; String type = nd.getNodeName(); String name = null; if (nd.hasAttributes()) { NamedNodeMap attrs = nd.getAttributes(); Node nameNd = attrs.getNamedItem("name"); if (nameNd != null) name=nameNd.getNodeValue(); } Object val=null; if ("str".equals(type)) { val = getText(nd); } else if ("int".equals(type)) { val = Integer.valueOf(getText(nd)); } else if ("long".equals(type)) { val = Long.valueOf(getText(nd)); } else if ("float".equals(type)) { val = Float.valueOf(getText(nd)); } else if ("double".equals(type)) { val = Double.valueOf(getText(nd)); } else if ("bool".equals(type)) { val = StrUtils.parseBool(getText(nd)); } else if ("lst".equals(type)) { val = childNodesToNamedList(nd); } else if ("arr".equals(type)) { val = childNodesToList(nd); } if (nlst != null) nlst.add(name,val); if (arr != null) arr.add(val); }
NamedList很好的支持嵌套,例如如下配置:
<?xml version="1.0" encoding="UTF-8"?> <param> <str name="client">client</str> <str name="fields">HTTPBody</str> <lst name="checker"> <str name="class">myclass</str> <lst name="initArgs"> <arr name="check-fields"> <str>PageTitle</str> <str>PageContent</str> </arr> <lst name="sublist"> <str name="txt">text</str>> <lst name="child"> <str name="childtext">text</str>> </lst>> </lst>> </lst> </lst> </param>
解析上述xml文件,代码如下:
package test; import java.io.IOException; import java.util.ArrayList; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathExpression; import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathFactory; import org.apache.solr.common.util.NamedList; import org.w3c.dom.Document; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; public class NamedListTest { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub String xmlpath = "/param"; getAttrs(xmlpath); } private static void getAttrs(String expression) { DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance(); domFactory.setNamespaceAware(true); DocumentBuilder builder; try { builder = domFactory.newDocumentBuilder(); Document doc = builder.parse("NewFile.xml"); XPath xpath = XPathFactory.newInstance().newXPath(); XPathExpression expr = xpath.compile(expression); NodeList nodes = (NodeList) expr.evaluate(doc, XPathConstants.NODESET); //System.out.println("ssss " + nodes.getLength()); for (int i = 0; i < nodes.getLength(); ++i) { NamedList<Object> namedList = DOMUtil.childNodesToNamedList(nodes.item(i)); System.out.println(namedList.toString()); NamedList<Object> parserPosDataChecker = (NamedList<Object>) namedList.get("checker"); System.out.println("class " + parserPosDataChecker.get("class")) ; NamedList<Object> checkList = (NamedList<Object>) parserPosDataChecker.get("initArgs"); ArrayList<String> checkArr = (ArrayList<String>)checkList.get("check-fields"); System.out.println(checkArr.toString()); } } catch (ParserConfigurationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SAXException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (XPathExpressionException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
代码需要DOMUtil和StrUtils的支持,这两个可以从Solr源码中直接取出就可以用,解析xml时用到了XPath,不熟悉的同学可以先看看XPath,然后再学习本实例。