当前位置: 首页 > 知识库问答 >
问题:

JavaVTD-XML和XPath:在找到的部分使用XPath

劳仲渊
2023-03-14

我有以下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代码段:(只是隔离问题的代码)

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();

在找到名称为File的类型的一个部分后,我想从该部分获取文件名和大小。(当然,稍后会更多一点,但就我的理解而言,这就足够了)。

代码现在的问题是,它确实找到了匹配的值,但SIZE不是File中的子级。

输出:

NAME ==> Smile.JPG
NAME ==> OldMan.JPG

SIZE ==> 10241624
SIZE ==> 821563412

我有两个AutoPilot,一个用于主要部分,我有用第二个AutoPilot进行内部搜索的想法。

有人能帮我只在第一个找到的部分“搜索”吗?我想要一些输出,比如:

NAME ==> Smile.JPG
SIZE ==> 10241624

NAME ==> OldMan.JPG
SIZE ==> 821563412

共有1个答案

夹谷成龙
2023-03-14

您的示例代码至少有2个IMO问题,至少在我对VTD-XML的理解中是这样。首先,文件名和大小的xpath查询对我来说似乎很奇怪,因为它们不包含像///这样的根。接下来,最好提取file-id并将它们添加到XPath查询中。

我把你的代码修改了一点

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();
  }
}

产生以下输出

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

请注意,如果您使用XPath查询,如/project/category[@type=“Files”]/type/@id,而不是//category[@type=“Files”]/type/@id,则只会列出第一个值文件元素。不确定为什么VTD-XML不能迭代所有元素。

 类似资料:
  • 我无法使用XPATH和CSS找到元素

  • 我有这样的validLog4jXML字符串 我尝试运行以下代码: 在最后一行,我得到了例外: 我试图查看关于VTD-XML的文档,它说: 为避免此异常: com.ximpleware。XPathParseException:未找到前缀xyz的URL 确保创建具有命名空间支持的初始navigator对象(即,最后一个参数设置为true),并将命名空间哈希作为最终参数传递,以查找索引、第一个匹配、所有

  • 我尝试了xpath和检查,如下所示

  • 我尝试使用Python selenium(新的)做一些自动化。不幸的是,检查特定网页的元素不仅仅是困难的。没有id可以使用,我尝试xpath。我想选择一个下拉列表,我检查这个元素,然后复制xpath,它是//*[@id="frmMain:purchase_criteria_tab"]/div[13]/div[1]/div/按钮 我的代码是: 我不明白这个元素有什么想法吗?提前谢谢你。

  • 我必须在这个xml中设置“count”属性的值: 我想使用这样的代码(VTDXML库)使用“Foo”更改myCount值: 这样我反而获得了 那不是我的目标因为我想要的是

  • 问题内容: 我正在使用Java XML DSig API签名XML文档的一部分。我试图了解它是如何达到Digest值的。 我的文件是: 我的xpath表达式是: 我试图做的是: 调用Java DSIG库并查看生成的摘要的值。 使用MessageDigest(SHA-1)类可消化值“ bar”。 验证1和2中的摘要是否匹配。 当我这样做时,1和2会产生不同的摘要值。我对DSIG代码的处理完全不对,或