2014-09-30 28 views
4

我試圖找到與蠟染的SVG文件的一些元素。掌握XPath的特定元素從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> 

我試圖找到所有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」'。嘗試註冊該名稱空間。 – 2014-09-30 07:45:42

+0

我發現這非常有用,但我無法使它工作。顯然有'batik'和'xerces'的版本相沖突。你使用什麼版本? – clapas 2015-07-08 11:06:12

+1

對於那些感興趣的人,我終於可以通過使用'org.apache.xpath.XPathAPI'來代替'org.w3c.dom.xpath.XPathEvaluator',但是在另一個類似的實現中。歡呼聲 – clapas 2015-07-08 11:35:50

回答

2

這是因爲默認的命名空間xmlns="http://www.w3.org/2000/svg"的。嘗試使用local-name()函數:

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

這是有效的,但它是一個相當醜陋的語法。沒有其他辦法嗎? 「註冊命名空間」是什麼意思?我可以爲XPathEvaluator設置默認名稱空間嗎?我認爲這是XPathNSResolver的用途,但我不明白如何使用它。 – radlan 2014-09-30 11:38:17