[英]Java VTD-XML and XPath: Use XPath in found section
I have the following XML File: 我有以下XML文件:
<project>
<category type="Files">
<type name="File" type="String" id="1">
<field name="Name" type="String">
<value type="String"><![CDATA[Smile.JPG]]></value>
</field>
<multiValue name="Entries" type="FileEntry">
<model type="Specs" state="Intact">
<field name="Value" type="String">
<value type="String"><![CDATA[10241624]]></value>
</field>
</model>
</multiValue>
</type>
<type name="File" type="String" id="2">
<field name="Name" type="String">
<value type="String"><![CDATA[OldMan.JPG]]></value>
</field>
<multiValue name="Entries" type="FileEntry">
<model type="Specs" state="Gone">
<field name="Category" type="String">
<value type="String"><![CDATA[Size]]></value>
</field>
<field name="Value" type="String">
<value type="String"><![CDATA[821563412]]></value>
</field>
</model>
</multiValue>
</type>
</category>
</project>
java code snippet: (Just the code to isolate the issue) java代码段:(只需代码即可隔离问题)
VTDGen vg = new VTDGen();
int i;
AutoPilot ap = new AutoPilot();
ap.selectXPath("/project/category[@type=\"Files\"]");
AutoPilot ap2 = new AutoPilot();
BookMark bm = new BookMark();
vg.parseFile("stackoverflow_example.xml", false);
VTDNav vn = vg.getNav();
ap.bind(vn);
ap2.bind(vn);
/* main XPath selection */
ap.selectXPath("/project/category[@type=\"Files\"]");
/* part 1 */
//XPath eval returns one node at a time
ap2.selectXPath("type[@name=\"File\"]/field/value/text()");
while ((i = ap.evalXPath()) != -1) {
bm.recordCursorPosition(); // equivalent to vn.push();
int j;
while ((j = ap2.evalXPath()) != -1) {
logger.debug(" NAME ==> " + vn.toString(j));
}
ap2.resetXPath();
bm.setCursorPosition(); // equivalent to vn.pop();
}
ap.resetXPath();
/* part 2 */
ap2.selectXPath("type[@name=\"File\"]/multiValue/model[@type=\"Specs\"]/field[@name=\"Value\"]/value/text()");
while ((i = ap.evalXPath()) != -1) {
bm.recordCursorPosition(); // equivalent to vn.push();
int j;
while ((j = ap2.evalXPath()) != -1) {
logger.debug(" SIZE ==> " + vn.toString(j));
}
ap2.resetXPath();
bm.setCursorPosition(); // equivalent to vn.pop();
}
ap.resetXPath();
And after finding one section of the type with the name File, I want to get the filename and size from this section. 在找到名称为File的类型的一部分之后,我想从这一部分获取文件名和大小。 (Of course, later on a bit more, but for my understanding, this would be sufficient). (当然,稍后再讲,但是就我的理解而言,这已经足够了)。
The problem with the code is now, that it does find the matching values, but the SIZE is not a child from the File. 现在,代码的问题是,它确实找到了匹配的值,但是SIZE不是File中的子元素。
Output: 输出:
NAME ==> Smile.JPG
NAME ==> OldMan.JPG
SIZE ==> 10241624
SIZE ==> 821563412
I have two AutoPilots, one for the main section and I had the idea to inner-search with the second AutoPilot. 我有两个自动驾驶仪,一个用于主要部分,我想用第二个自动驾驶仪进行内部搜索。
Can anybody help only "search" in the first found section? 有人可以只在找到的第一个部分中帮助“搜索”吗? I would like to have some output like: 我想要一些输出,例如:
NAME ==> Smile.JPG
SIZE ==> 10241624
NAME ==> OldMan.JPG
SIZE ==> 821563412
Your sample code has at least 2 issues IMO, at least in my understanding of VTD-XML. 至少在我对VTD-XML的理解中,您的示例代码至少有2个问题IMO。 First, the xpath queries for the file name and size seem strange to me as they don't contain a root like /
or //
. 首先,对于文件名和大小的xpath查询对我来说似乎很奇怪,因为它们不包含/
或//
类的根。 Next, it would be preferrable to extract the file-id's and add them to the XPath queries. 接下来,最好提取文件ID并将其添加到XPath查询中。
I took your code and tweaked it a bit 我拿了你的代码并做了一些调整
import com.ximpleware.AutoPilot;
import com.ximpleware.VTDGen;
import com.ximpleware.VTDNav;
import java.io.File;
import java.lang.invoke.MethodHandles;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class StackOverflowExample {
private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
public static void main(String ... args) throws Exception {
VTDGen vg = new VTDGen();
File testFile = new File(StackOverflowExample.class.getResource("/stackoverflow_example.xml").toURI());
vg.parseFile(testFile.getAbsolutePath(), false);
VTDNav vn = vg.getNav();
AutoPilot ap = new AutoPilot();
ap.bind(vn);
AutoPilot ap2 = new AutoPilot();
ap2.bind(vn);
// iterate over all file IDs
int i;
ap.selectXPath("//category[@type=\"Files\"]/type/@id");
while ((i = ap.evalXPath()) != -1) {
int j;
// retrieve the value of the id attribute field
String attributeName = vn.toString(i);
int attributeId = vn.getAttrVal(attributeName);
String attributeVal = vn.toString(attributeId);
// add the id value to the respective xpath query
ap2.selectXPath("//category[@type=\"Files\"]/type[@name=\"File\" and @id=\"" + attributeVal + "\"]/field/value/text()");
while ((j = ap2.evalXPath()) != -1) {
LOG.debug(" NAME ==> " + vn.toString(j));
}
ap2.resetXPath();
ap2.selectXPath("//category[@type=\"Files\"]/type[@name=\"File\" and @id=\"" + attributeVal + "\"]/multiValue/model[@type=\"Specs\"]/field[@name=\"Value\"]/value/text()");
while ((j = ap2.evalXPath()) != -1) {
LOG.debug(" SIZE ==> " + vn.toString(j));
}
ap2.resetXPath();
}
ap.resetXPath();
}
}
which produces the following output 产生以下输出
11:57:07.196 [main] DEBUG StackOverflowExample - NAME ==> Smile.JPG
11:57:07.201 [main] DEBUG StackOverflowExample - SIZE ==> 10241624
11:57:07.202 [main] DEBUG StackOverflowExample - NAME ==> OldMan.JPG
11:57:07.204 [main] DEBUG StackOverflowExample - SIZE ==> 821563412
Note that if you use an XPath query like /project/category[@type="Files"]/type/@id
instead of //category[@type="Files"]/type/@id
only the first value file element will be listed. 请注意,如果您使用类似/project/category[@type="Files"]/type/@id
之//category[@type="Files"]/type/@id
的XPath查询,而不是//category[@type="Files"]/type/@id
仅第一个值文件元素将被列出。 Not sure why VTD-XML does not iterate over all the elements. 不知道为什么VTD-XML不会遍历所有元素。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.