1
votes

I'm trying to access elements of an SVG file using WebKitGtk but I'm failing miserably. The program is in Vala, it's very simple and is just an attempt at getting data from a couple of elements:

using Gtk;
using WebKit;

public class WebKitTest : Window {

    private WebView web_view;
    private const string uri = "file:///tmp/test.svg";

    public WebKitTest () {
        set_default_size (800, 600);
        web_view = new WebView ();
        var scrolled_window = new ScrolledWindow (null, null);
        scrolled_window.set_policy (PolicyType.AUTOMATIC, PolicyType.AUTOMATIC);
        scrolled_window.add (this.web_view);
        var vbox = new VBox (false, 0);
        vbox.add (scrolled_window);
        add (vbox);

        this.destroy.connect (Gtk.main_quit);

        show_all ();
        this.web_view.load_uri (WebKitTest.uri);
        var dom = web_view.get_dom_document ();
        var el = dom.get_document_element ();
        var child = el.first_element_child;
        stdout.printf ("%s\n", child.tag_name);

        var list = dom.get_elements_by_tag_name ("svg");
        stdout.printf ("%lu\n", list.length);
        assert (list == null);

        var length = list.length;
        assert (length == 0);

        var svg = list.item (0);
        var res = dom.evaluate ("//path", svg, null, 0, null);
        DOMNode node;
        while ((node = res.iterate_next ()) != null) {
            stdout.printf ("%s\n", (node as DOMElement).tag_name);
        }
    }

    public static void main (string[] args) {
        Gtk.init (ref args);
        var test = new WebKitTest ();
        Gtk.main ();
        return 0;
    }
}

This compiles with valac --pkg webkitgtk-3.0 --pkg gtk+-3.0 webkittest.vala but if you've only got Gtk3 installed like I have you unfortunately need to do copy the webkit-1.0 .vapi and .deps files to new webkitgtk-3.0 ones and replace the occurrences of gdk-2.0 and gtk-2.0 in the .deps file to be gdk-3.0 and gtk-3.0 respectively.

I would think that using the DOM to access sub elements of an SVG would be simple, but as soon as this code gets to the print statement for child.tag_name it gives "HEAD" and nowhere in the file is that found. The file I'm loading should be pretty standard seeing as I used inkscape to make it.

Does WebKit do something funny that I'm not seeing to documents that it loads?

Thanks.

Update:

It definitely seems that WebKit loads everything into an HTML document because when I use GObject to retrieve the Type and print it for the node returned by get_elements_by_tag_name("body") I get WebKitDOMHTMLBodyElement. Be that as it may I tried to do the following XPath query on the DOMDocument

var nsres = dom.create_ns_resolver (body);
DOMXPathResult res = null;
try {
    res = dom.evaluate ("//*", body, nsres, 0, null);
} catch (Error e) {
    stderr.printf ("%s\n", e.message);
}

DOMNode node;
try {
    while ((node = res.iterate_next ()) != null) {
        stdout.printf ("%s\n", (node as DOMElement).tag_name);
    }
} catch (Error e) {
    stderr.printf ("%s\n", e.message);
}

and all I get for output is

HTML
HEAD
BODY

I'm lost now. The SVG file clearly loads correctly but it isn't part of the document?

1

1 Answers

0
votes

I believe Webkit has a quirk where, if it doesn't know the MIME type of a document, it will wrap it in <html> tags. So I suspect the document you are trying to access has been transformed by Webkit into something like:

<html>
  <head />
  <body>
    <svg>...etc...</svg>
  </body>
</html>

That's why you are seeing a <head> tag in your code.

As a suggestion, try using Vala's equivalent of getElementsByTagName() to find your <svg> tag. From a quick look at the docs, it should be something like:

    var dom = web_view.get_dom_document();
    var el = dom.get_elements_by_tag_name("svg").item(0);
    var child = var child = el.first_element_child;

Alternatively, if there is a way to tell WebKit/WebFrame that the MIME type of the file is "image/svg+xml", then that should also solve your problem.