现在已经多次询问过这个问题的变体,但我的问题更多的是在Java中使用XPATH的一般效率问题。
我的任务:获取有关地理位置的维基百科文章,并从中创建分层数据结构。
我已经获得了维基页面的XML版本,并根据具有直观意义的架构重新格式化。我还创建了一系列非常简单的类来表示不同级别的管理层次结构,例如:
public class Province implements java.io.Serializable {
private ArrayList<City> cities = new ArrayList<City>();
private String hanzi;
private String pinyin;
public Province(String hanzi, String pinyin) {
this.hanzi = hanzi;
this.pinyin = pinyin;
}
除了添加城市的方法,一些getter和setter方法,以及toString()。
以下是我正在处理的XML文件类型的示例:
<mediawiki>
<page>
<title>Tianjin</title>
<revision>
<id>2064019</id>
<text xml:space="preserve">
<province>
<hanzi>天津</hanzi>
<pinyin>Tianjin</pinyin>
<Level2>
<hanzi>和平</hanzi>
<pinyin>Heping</pinyin>
<zip>300000</zip>
</Level2>
<Level2>
<hanzi>河东</hanzi>
<pinyin>Hedong</pinyin>
<zip>300000</zip>
</Level2>
</province>
</text>
</revision>
</page>
...
</mediawiki>
此时我基本上有一个功能设置,但代码非常重复,并没有考虑地理数据固有的分层性质。理想情况下,我可以停留在某个级别(让我们说“专注于某一特定省份”),并且仅从相关的角度来指代那些事情,以最小化我必须遍历整个文档的次数。作为一个例子(请注意,我使用的是传统文档设置的抽象,但下面的方法几乎完全符合传统方法):
XPathReader reader = new XPathReader("sourceXML\\Provinces.xml");
String expression = "/mediawiki/page";
NodeList allProvinces = (NodeList)reader.read(expression, XPathConstants.NODESET);
for(int i=0; i < allProvinces.getLength(); i++) {
expression = "/mediawiki/page[" + i + "]/revision/text/province/hanzi";
String hanzi = reader.read(expression, XPathConstants.STRING).toString();
expression = "/mediawiki/page[" + i + "]/revision/text/province/pinyin";
String pinyin = reader.read(expression, XPathConstants.STRING).toString();
Province currProv = new Province(hanzi, pinyin);
expression = "/mediawiki/page[" + i + "]/revision/text/province/Level2";
NodeList level2 = (NodeList)reader.read(expression, XPathConstants.NODESET);
for(int j=1; j < level2.getLength(); j++) {
expression = "/mediawiki/page[" + i + "]/revision/text/province/Level2[" + j + "]/hanzi";
String hanzi2 = reader.read(expression, XPathConstants.STRING).toString();
expression = "/mediawiki/page[" + i + "]/revision/text/province/Level2[" + j + "]/pinyin";
String pinyin2 = reader.read(expression, XPathConstants.STRING).toString();
City currCity = new City(hanzi2, pinyin2);
currProv.add(currCity);
...
}
}
坦率地说,这看起来很愚蠢。我没有考虑到这样一个事实,即一旦我达到我关注的水平,这些字符串的所有内容都是相同的。我没有引用任何类型的相对路径,每当我遍历文档的一部分时,我实际上遍历整个事物。如果我可以暂时阻止原始XML文档的其余部分并且只关注我的省份,那将是很好的,从而相对而言是指所有相关的东西。
我应该特别注意“读取”抽象背后的成本有多贵:
xPath.compile(expression);
String result = xPathExpression.evaluate (xmlDocument, returnType);
我基本上是在重新编译相同的模式,结尾略有不同?加载感兴趣的部分,然后用“currProv / hanzi”之类的东西引用它的孩子怎么样?
我已经研究过解析XML的其他方法,而“Digester”似乎做了类似于我想要的事情http://commons.apache.org/digester/core.html,但我已经拥有了这个XPATH实现中的几乎所有东西。
我有一种唠叨的怀疑,即这个问题的解决方案非常简单......但我无法完全掌握解决方案。无论如何,我感谢你的时间!
答案 0 :(得分:1)
相对嵌套的XPath是要走的路。
我领导EclipseLink JAXB实现(MOXy),我们通过@XmlPath注释提供此功能。如果你已经有了XPath,那将是一个相对容易的映射。
有关详细信息,请参阅: