【问题标题】:Getting specific elements with XPath from an SVG with Batik使用 Batik 从 SVG 中使用 XPath 获取特定元素
【发布时间】:2014-11-24 17:21:24
【问题描述】:

我正在尝试使用 Batik 从 SVG 文档中查找一些元素。

这是我正在使用的示例 SVG 文档:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>

<svg
   xmlns:svg="http://www.w3.org/2000/svg"
   xmlns="http://www.w3.org/2000/svg"
   version="1.0"     
   width="400"
   height="300"
   viewBox="0 -100 400 300"
   preserveAspectRatio="none"
   id="svg2">

  <g id="blubb">
   <line x1="0" y1="0" x2="40" y2="120" stroke="red" stroke-width="3"/>
   <text class="hurz" x="50" y="150">HURZ!</text>
  </g>
</svg>

我正在尝试查找所有具有类属性hurztext 元素。

这是一个示例代码:

import java.awt.*;
import java.io.*;
import javax.swing.*;
import org.apache.batik.swing.*;
import org.apache.batik.swing.gvt.*;
import org.w3c.dom.*;
import org.w3c.dom.svg.*;
import org.w3c.dom.xpath.*;

public class XPathTest extends JFrame {
  private final JSVGCanvas c= new JSVGCanvas();


  public XPathTest(){
    this.setLayout(new GridLayout());
    this.add(c);

    c.setURI(new File("/tmp/bla.svg").toURI().toString());

    c.addGVTTreeRendererListener(new GVTTreeRendererAdapter() {
      @Override
      public void gvtRenderingCompleted(GVTTreeRendererEvent e) {
        testXPath();
      }
    });
  }

  private void testXPath() {
    final SVGDocument document= c.getSVGDocument();
    final XPathEvaluator xpathEvaluator= (XPathEvaluator) document;
    final SVGElement searchRoot= (SVGElement) document.getElementById("blubb");

    //works
    final XPathResult result1= (XPathResult) xpathEvaluator.evaluate(".//*[@class=\"hurz\"]", searchRoot, null, XPathResult.ORDERED_NODE_ITERATOR_TYPE, null);
    printResults(result1);

    //doesn't work                                                                                                                              
    final XPathResult result2= (XPathResult) xpathEvaluator.evaluate(".//text[@class=\"hurz\"]", searchRoot, null, XPathResult.ORDERED_NODE_ITERATOR_TYPE, null);
    printResults(result2);

    //doesn't work
    final XPathResult result3= (XPathResult) xpathEvaluator.evaluate(".//text", searchRoot, null, XPathResult.ORDERED_NODE_ITERATOR_TYPE, null);
    printResults(result3);
  }

  private void printResults(XPathResult result){
    int count= 0;

    Node node;
    while ((node= result.iterateNext()) != null) {
      count++;
    }

    System.out.println(count);
  }

  public static void main(String[] args){
    final XPathTest f= new XPathTest();
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    f.setSize(800, 600);
    f.setVisible(true);
  }
}

运行时,输出为:

1
0
0

很明显,XPath 表达式.//*[@class="hurz"] 找到了正确的节点。但是,当我搜索特定元素类型(在本例中为 text 元素)时,它找不到与表达式 .//text[@class="hurz"].//text 一样的内容。

我做错了什么还是蜡染中的一个错误?

【问题讨论】:

  • 这是因为默认命名空间xmlns="http://www.w3.org/2000/svg"。尝试注册该命名空间。
  • 我发现这非常有用,但我无法让它发挥作用。显然batikxerces 的版本存在冲突。你用的是什么版本?
  • 对于那些感兴趣的人,我终于通过使用org.apache.xpath.XPathAPI 而不是org.w3c.dom.xpath.XPathEvaluator 在替代但类似的实现中使其工作。干杯

标签: java xpath svg batik


【解决方案1】:

这是因为默认命名空间xmlns="http://www.w3.org/2000/svg"。尝试使用local-name() 函数:

.//*[local-name()=\"text\" and @class=\"hurz\"]

【讨论】:

  • 这行得通,但它的语法很丑陋。难道没有别的办法了吗? “注册命名空间”是什么意思?我可以为 XPathEvaluator 设置默认名称空间吗?我认为这就是 XPathNSResolver 的用途,但我不明白如何使用它。
  • 其实没那么难看。除非不可能使用 xpath 显式获取 svg 元素,例如div,我们可以获取任何元素(*)并通过类或其他属性来识别它。
猜你喜欢
  • 2022-01-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-13
  • 2018-05-25
  • 1970-01-01
相关资源
最近更新 更多