2014-09-30 2 views
4

Я пытаюсь найти некоторые элементы из документа SVG с помощью Batik.Получение конкретных элементов с XPath из SVG с помощью Batik

Это пример 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> 

Я пытаюсь найти все text элементы с атрибутом класса hurz.

Это пример кода:

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.

Я делаю что-то неправильно или это ошибка в Батике?

+0

Это из пространства имен по умолчанию 'XMLNS = "http://www.w3.org/2000/svg"'. Попробуйте зарегистрировать это пространство имен. –

+0

Я нашел это очень полезным, но я не могу заставить его работать. По-видимому, существуют противоречивые версии 'batik' и' xerces'. Какие версии вы используете? – clapas

+1

Для тех, кого это интересует, я, наконец, получил его, используя «org.apache.xpath.XPathAPI» вместо 'org.w3c.dom.xpath.XPathEvaluator' в альтернативной, но аналогичной реализации. Cheers – clapas

ответ

2

Это из-за пространства имен по умолчанию xmlns="http://www.w3.org/2000/svg". Попробуйте использовать функцию local-name():

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

Это работает, но это довольно уродливый синтаксис. Разве нет другого пути? Что вы понимаете под «регистрацией пространства имен»? Можно ли задать пространство имен по умолчанию для XPathEvaluator? Я предполагаю, что это XPathNSResolver, но я не понимаю, как его использовать. – radlan

 Смежные вопросы

  • Нет связанных вопросов^_^