[librsvg: 8/20] Convert everything from LocalName to QualName



commit e25c7442e82b97e84ed0bdafc3915917516427a5
Author: Federico Mena Quintero <federico gnome org>
Date:   Thu Oct 24 19:41:36 2019 -0500

    Convert everything from LocalName to QualName

 Cargo.lock                                       | 416 ++++++++++++++---------
 rsvg_internals/Cargo.toml                        |   2 +-
 rsvg_internals/src/clip_path.rs                  |   6 +-
 rsvg_internals/src/create_node.rs                |  52 +--
 rsvg_internals/src/css.rs                        |  12 +-
 rsvg_internals/src/error.rs                      |  20 +-
 rsvg_internals/src/filters/blend.rs              |  10 +-
 rsvg_internals/src/filters/color_matrix.rs       |  16 +-
 rsvg_internals/src/filters/component_transfer.rs |  20 +-
 rsvg_internals/src/filters/composite.rs          |  16 +-
 rsvg_internals/src/filters/convolve_matrix.rs    |  28 +-
 rsvg_internals/src/filters/displacement_map.rs   |  14 +-
 rsvg_internals/src/filters/gaussian_blur.rs      |   6 +-
 rsvg_internals/src/filters/image.rs              |   8 +-
 rsvg_internals/src/filters/input.rs              |   4 +-
 rsvg_internals/src/filters/light/light_source.rs |  34 +-
 rsvg_internals/src/filters/light/lighting.rs     |  18 +-
 rsvg_internals/src/filters/merge.rs              |   6 +-
 rsvg_internals/src/filters/mod.rs                |  18 +-
 rsvg_internals/src/filters/morphology.rs         |  10 +-
 rsvg_internals/src/filters/node.rs               |  18 +-
 rsvg_internals/src/filters/offset.rs             |   8 +-
 rsvg_internals/src/filters/turbulence.rs         |  18 +-
 rsvg_internals/src/gradient.rs                   |  42 +--
 rsvg_internals/src/image.rs                      |  16 +-
 rsvg_internals/src/link.rs                       |   6 +-
 rsvg_internals/src/marker.rs                     |  20 +-
 rsvg_internals/src/mask.rs                       |  16 +-
 rsvg_internals/src/node.rs                       |  24 +-
 rsvg_internals/src/parsers.rs                    |   4 +-
 rsvg_internals/src/pattern.rs                    |  26 +-
 rsvg_internals/src/properties.rs                 | 110 +++---
 rsvg_internals/src/property_bag.rs               | 168 +++------
 rsvg_internals/src/shapes.rs                     |  50 +--
 rsvg_internals/src/structure.rs                  |  34 +-
 rsvg_internals/src/style.rs                      |   4 +-
 rsvg_internals/src/text.rs                       |  26 +-
 rsvg_internals/src/util.rs                       |  32 ++
 rsvg_internals/src/xml.rs                        | 113 +++---
 rsvg_internals/src/xml2_load.rs                  |  20 +-
 40 files changed, 758 insertions(+), 713 deletions(-)
---
diff --git a/Cargo.lock b/Cargo.lock
index 840e995f..855d3ab8 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -29,10 +29,10 @@ dependencies = [
 
 [[package]]
 name = "arrayvec"
-version = "0.4.11"
+version = "0.4.12"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 dependencies = [
- "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "nodrop 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -40,18 +40,18 @@ name = "atty"
 version = "0.2.13"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 dependencies = [
- "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "autocfg"
-version = "0.1.6"
+version = "0.1.7"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 
 [[package]]
 name = "bitflags"
-version = "1.1.0"
+version = "1.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 
 [[package]]
@@ -67,7 +67,7 @@ dependencies = [
  "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex-automata 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.100 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -75,17 +75,25 @@ name = "byteorder"
 version = "1.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 
+[[package]]
+name = "c2-chacha"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+dependencies = [
+ "ppv-lite86 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "cairo-rs"
 version = "0.7.1"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 dependencies = [
- "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "cairo-sys-rs 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "glib 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "glib 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "glib-sys 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "gobject-sys 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -94,7 +102,7 @@ version = "0.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 dependencies = [
  "glib-sys 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
  "pkg-config 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -106,7 +114,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index";
 
 [[package]]
 name = "cfg-if"
-version = "0.1.9"
+version = "0.1.10"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 
 [[package]]
@@ -114,7 +122,7 @@ name = "clap"
 version = "2.33.0"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 dependencies = [
- "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -124,7 +132,7 @@ name = "cloudabi"
 version = "0.0.3"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 dependencies = [
- "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -139,16 +147,16 @@ dependencies = [
  "csv 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "rand_xoshiro 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rayon-core 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.100 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.100 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)",
  "tinytemplate 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -177,8 +185,8 @@ name = "crossbeam-epoch"
 version = "0.7.2"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 dependencies = [
- "arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "memoffset 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -198,7 +206,7 @@ name = "crossbeam-utils"
 version = "0.6.6"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 dependencies = [
- "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -207,13 +215,13 @@ name = "cssparser"
 version = "0.25.9"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 dependencies = [
- "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "cssparser-macros 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "dtoa-short 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "phf 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)",
- "proc-macro2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "procedural-masquerade 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -226,7 +234,7 @@ version = "0.3.6"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 dependencies = [
  "phf_codegen 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)",
- "proc-macro2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "procedural-masquerade 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -240,8 +248,8 @@ dependencies = [
  "bstr 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "csv-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.100 (registry+https://github.com/rust-lang/crates.io-index)",
+ "ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -262,7 +270,7 @@ dependencies = [
 
 [[package]]
 name = "downcast-rs"
-version = "1.0.4"
+version = "1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 
 [[package]]
@@ -280,7 +288,7 @@ dependencies = [
 
 [[package]]
 name = "either"
-version = "1.5.2"
+version = "1.5.3"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 
 [[package]]
@@ -375,10 +383,10 @@ dependencies = [
  "gdk-pixbuf-sys 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "gio 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "gio-sys 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "glib 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "glib 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "glib-sys 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "gobject-sys 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -389,7 +397,7 @@ dependencies = [
  "gio-sys 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "glib-sys 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "gobject-sys 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
  "pkg-config 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -401,19 +409,29 @@ dependencies = [
  "typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "getrandom"
+version = "0.1.12"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+dependencies = [
+ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
+ "wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "gio"
 version = "0.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 dependencies = [
- "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "fragile 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "gio-sys 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "glib 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "glib 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "glib-sys 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "gobject-sys 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -423,20 +441,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index";
 dependencies = [
  "glib-sys 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "gobject-sys 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
  "pkg-config 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "glib"
-version = "0.8.1"
+version = "0.8.2"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 dependencies = [
- "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "glib-sys 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "gobject-sys 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -444,7 +462,7 @@ name = "glib-sys"
 version = "0.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 dependencies = [
- "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
  "pkg-config 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -454,7 +472,7 @@ version = "0.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 dependencies = [
  "glib-sys 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
  "pkg-config 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -473,7 +491,7 @@ name = "itertools"
 version = "0.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 dependencies = [
- "either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -493,7 +511,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index";
 
 [[package]]
 name = "libc"
-version = "0.2.62"
+version = "0.2.65"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 
 [[package]]
@@ -507,7 +525,7 @@ version = "2.46.0"
 dependencies = [
  "cairo-rs 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "gio 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "glib 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "glib 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "pkg-config 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
  "rsvg_internals 0.0.1",
  "url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -517,17 +535,17 @@ dependencies = [
 name = "librsvg_c_api"
 version = "0.0.1"
 dependencies = [
- "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "cairo-rs 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "cairo-sys-rs 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "gdk-pixbuf 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "gdk-pixbuf-sys 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "gio 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "gio-sys 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "glib 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "glib 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "glib-sys 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "gobject-sys 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
  "rsvg_internals 0.0.1",
  "url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -538,7 +556,7 @@ version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 dependencies = [
  "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "objc 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "objc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "objc-foundation 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -549,7 +567,7 @@ name = "log"
 version = "0.4.8"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 dependencies = [
- "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -562,22 +580,22 @@ name = "malloc_buf"
 version = "0.0.6"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 dependencies = [
- "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "markup5ever"
-version = "0.9.0"
+version = "0.10.0"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 dependencies = [
  "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "phf 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)",
- "phf_codegen 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.100 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.100 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
- "string_cache 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "string_cache_codegen 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "phf 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "phf_codegen 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)",
+ "string_cache 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "string_cache_codegen 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "tendril 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -588,10 +606,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index";
 
 [[package]]
 name = "matrixmultiply"
-version = "0.2.2"
+version = "0.2.3"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 dependencies = [
- "rawpointer 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rawpointer 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -599,7 +617,7 @@ name = "memchr"
 version = "2.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 dependencies = [
- "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -618,7 +636,7 @@ dependencies = [
  "alga 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "approx 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "matrixmultiply 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "matrixmultiply 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-complex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-rational 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -633,7 +651,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index";
 
 [[package]]
 name = "nodrop"
-version = "0.1.13"
+version = "0.1.14"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 
 [[package]]
@@ -641,7 +659,7 @@ name = "num-complex"
 version = "0.2.3"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 dependencies = [
- "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -650,7 +668,7 @@ name = "num-integer"
 version = "0.1.41"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 dependencies = [
- "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -659,7 +677,7 @@ name = "num-rational"
 version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 dependencies = [
- "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -669,7 +687,7 @@ name = "num-traits"
 version = "0.2.8"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 dependencies = [
- "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -677,12 +695,12 @@ name = "num_cpus"
 version = "1.10.1"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 dependencies = [
- "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "objc"
-version = "0.2.6"
+version = "0.2.7"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 dependencies = [
  "malloc_buf 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -694,7 +712,7 @@ version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 dependencies = [
  "block 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "objc 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "objc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "objc_id 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -703,7 +721,7 @@ name = "objc_id"
 version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 dependencies = [
- "objc 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "objc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -711,12 +729,12 @@ name = "pango"
 version = "0.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 dependencies = [
- "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "glib 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "glib 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "glib-sys 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "gobject-sys 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
  "pango-sys 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -727,7 +745,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index";
 dependencies = [
  "glib-sys 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "gobject-sys 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
  "pkg-config 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -736,13 +754,13 @@ name = "pangocairo"
 version = "0.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 dependencies = [
- "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "cairo-rs 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "cairo-sys-rs 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "glib 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "glib 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "glib-sys 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "gobject-sys 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
  "pango 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "pango-sys 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "pangocairo-sys 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -755,7 +773,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index";
 dependencies = [
  "cairo-sys-rs 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "glib-sys 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
  "pango-sys 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "pkg-config 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -773,6 +791,14 @@ dependencies = [
  "phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "phf"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+dependencies = [
+ "phf_shared 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "phf_codegen"
 version = "0.7.24"
@@ -782,6 +808,15 @@ dependencies = [
  "phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "phf_codegen"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+dependencies = [
+ "phf_generator 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "phf_shared 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "phf_generator"
 version = "0.7.24"
@@ -791,6 +826,15 @@ dependencies = [
  "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "phf_generator"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+dependencies = [
+ "phf_shared 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "phf_shared"
 version = "0.7.24"
@@ -799,27 +843,32 @@ dependencies = [
  "siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "phf_shared"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+dependencies = [
+ "siphasher 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "pkg-config"
 version = "0.3.16"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 
 [[package]]
-name = "precomputed-hash"
-version = "0.1.1"
+name = "ppv-lite86"
+version = "0.2.6"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 
 [[package]]
-name = "proc-macro2"
-version = "0.4.30"
+name = "precomputed-hash"
+version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-dependencies = [
- "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
-]
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.3"
+version = "1.0.6"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 dependencies = [
  "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -830,20 +879,12 @@ name = "procedural-masquerade"
 version = "0.1.6"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 
-[[package]]
-name = "quote"
-version = "0.6.13"
-source = "registry+https://github.com/rust-lang/crates.io-index";
-dependencies = [
- "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
 [[package]]
 name = "quote"
 version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 dependencies = [
- "proc-macro2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -851,8 +892,8 @@ name = "rand"
 version = "0.6.5"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 dependencies = [
- "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
+ "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
  "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -864,15 +905,37 @@ dependencies = [
  "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "rand"
+version = "0.7.2"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+dependencies = [
+ "getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand_pcg 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "rand_chacha"
 version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 dependencies = [
- "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "rand_chacha"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+dependencies = [
+ "c2-chacha 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "rand_core"
 version = "0.3.1"
@@ -886,6 +949,14 @@ name = "rand_core"
 version = "0.4.2"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 
+[[package]]
+name = "rand_core"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+dependencies = [
+ "getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "rand_hc"
 version = "0.1.0"
@@ -894,6 +965,14 @@ dependencies = [
  "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "rand_hc"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+dependencies = [
+ "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "rand_isaac"
 version = "0.1.1"
@@ -907,7 +986,7 @@ name = "rand_jitter"
 version = "0.1.4"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 dependencies = [
- "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
  "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -919,7 +998,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index";
 dependencies = [
  "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
  "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -930,10 +1009,18 @@ name = "rand_pcg"
 version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 dependencies = [
- "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "rand_pcg"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+dependencies = [
+ "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "rand_xorshift"
 version = "0.1.1"
@@ -953,7 +1040,7 @@ dependencies = [
 
 [[package]]
 name = "rawpointer"
-version = "0.1.0"
+version = "0.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 
 [[package]]
@@ -962,7 +1049,7 @@ version = "1.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 dependencies = [
  "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "rayon-core 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1024,21 +1111,21 @@ dependencies = [
  "criterion 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "cssparser 0.25.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "data-url 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "downcast-rs 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "downcast-rs 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "encoding 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
  "float-cmp 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "gdk-pixbuf 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "gdk-pixbuf-sys 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "gio 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "gio-sys 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "glib 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "glib 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "glib-sys 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
  "locale_config 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "markup5ever 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "markup5ever 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "nalgebra 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "pango 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1062,7 +1149,7 @@ dependencies = [
 
 [[package]]
 name = "ryu"
-version = "1.0.0"
+version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 
 [[package]]
@@ -1093,27 +1180,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index";
 
 [[package]]
 name = "serde"
-version = "1.0.100"
+version = "1.0.101"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 
 [[package]]
 name = "serde_derive"
-version = "1.0.100"
+version = "1.0.101"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 dependencies = [
- "proc-macro2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "serde_json"
-version = "1.0.40"
+version = "1.0.41"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 dependencies = [
  "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.100 (registry+https://github.com/rust-lang/crates.io-index)",
+ "ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1121,6 +1208,11 @@ name = "siphasher"
 version = "0.2.3"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 
+[[package]]
+name = "siphasher"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+
 [[package]]
 name = "smallvec"
 version = "0.6.10"
@@ -1128,41 +1220,33 @@ source = "registry+https://github.com/rust-lang/crates.io-index";
 
 [[package]]
 name = "string_cache"
-version = "0.7.3"
+version = "0.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 dependencies = [
  "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "new_debug_unreachable 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)",
+ "phf_shared 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.100 (registry+https://github.com/rust-lang/crates.io-index)",
- "string_cache_codegen 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "string_cache_codegen"
-version = "0.4.2"
+version = "0.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 dependencies = [
- "phf_generator 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)",
- "phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)",
- "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
- "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)",
- "string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "phf_generator 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "phf_shared 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
-[[package]]
-name = "string_cache_shared"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index";
-
 [[package]]
 name = "syn"
 version = "1.0.5"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 dependencies = [
- "proc-macro2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -1198,8 +1282,8 @@ name = "tinytemplate"
 version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 dependencies = [
- "serde 1.0.100 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1228,11 +1312,6 @@ name = "unicode-width"
 version = "0.1.6"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 
-[[package]]
-name = "unicode-xid"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index";
-
 [[package]]
 name = "unicode-xid"
 version = "0.2.0"
@@ -1263,6 +1342,11 @@ dependencies = [
  "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "wasi"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+
 [[package]]
 name = "winapi"
 version = "0.3.8"
@@ -1299,17 +1383,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index";
 "checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = 
"58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d"
 "checksum alga 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = 
"d708cb68c7106ed1844de68f50f0157a7788c2909a6926fad5a87546ef6a4ff8"
 "checksum approx 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = 
"f0e60b75072ecd4168020818c0107f2857bb6c4e64252d8d3983f6263b40a5c3"
-"checksum arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = 
"b8d73f9beda665eaa98ab9e4f7442bd4e7de6652587de55b2525e52e29c1b0ba"
+"checksum arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = 
"cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9"
 "checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = 
"1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90"
-"checksum autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = 
"b671c8fb71b457dd4ae18c4ba1e59aa81793daacc361d82fcd410cef0d491875"
-"checksum bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = 
"3d155346769a6855b86399e9bc3814ab343cd3d62c7e985113d46a0ec3c281fd"
+"checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = 
"1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2"
+"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = 
"cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
 "checksum block 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = 
"0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a"
 "checksum bstr 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = 
"8d6c2c5b58ab920a4f5aeaaca34b4488074e8cc7596af94e6f8c6ff247c60245"
 "checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = 
"a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5"
+"checksum c2-chacha 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = 
"214238caa1bf3a496ec3392968969cab8549f96ff30652c9e56885329315f6bb"
 "checksum cairo-rs 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = 
"e05db47de3b0f09a222fa4bba2eab957d920d4243962a86b2d77ab401e4a359c"
 "checksum cairo-sys-rs 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = 
"90a1ec04603a78c111886a385edcec396dbfbc57ea26b9e74aeea6a1fe55dcca"
 "checksum cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = 
"926013f2860c46252efceabb19f4a6b308197505082c609025aa6706c011d427"
-"checksum cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = 
"b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33"
+"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = 
"4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
 "checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = 
"5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9"
 "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = 
"ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
 "checksum criterion 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = 
"0363053954f3e679645fc443321ca128b7b950a6fe288cf5f9335cc22ee58394"
@@ -1323,10 +1408,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index";
 "checksum csv 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = 
"37519ccdfd73a75821cac9319d4fce15a81b9fcf75f951df5b9988aa3a0af87d"
 "checksum csv-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = 
"9b5cadb6b25c77aeff80ba701712494213f4a8418fcda2ee11b6560c3ad0bf4c"
 "checksum data-url 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = 
"d33fe99ccedd6e84bc035f1931bb2e6be79739d6242bd895e7311c886c50dc9c"
-"checksum downcast-rs 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = 
"f2b92dfd5c2f75260cbf750572f95d387e7ca0ba5e3fbe9e1a33f23025be020f"
+"checksum downcast-rs 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = 
"5fe414cc2fd4447b7da94b27ddfb6831a8a06f35f6d077ab5613ec703866c49a"
 "checksum dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = 
"ea57b42383d091c85abcc2706240b94ab2a8fa1fc81c10ff23c4de06e2a90b5e"
 "checksum dtoa-short 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = 
"59020b8513b76630c49d918c33db9f4c91638e7d3404a28084083b87e33f76f2"
-"checksum either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = 
"5527cfe0d098f36e3f8839852688e63c8fff1c90b2b405aef730615f9a7bcf7b"
+"checksum either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = 
"bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3"
 "checksum encoding 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = 
"6b0d943856b990d12d3b55b359144ff341533e516d94098b1d3fc1ac666d36ec"
 "checksum encoding-index-japanese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = 
"04e8b2ff42e9a05335dbf8b5c6f7567e5591d0d916ccef4e0b1710d32a0d0c91"
 "checksum encoding-index-korean 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = 
"4dc33fb8e6bcba213fe2f14275f0963fd16f0a02c878e3095ecfdf5bee529d81"
@@ -1341,9 +1426,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index";
 "checksum gdk-pixbuf 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = 
"9726408ee1bbada83094326a99b9c68fea275f9dbb515de242a69e72051f4fcc"
 "checksum gdk-pixbuf-sys 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = 
"b1d6778abf5764b9080a9345a16c5d16289426a3b3edd808a29a9061d431c465"
 "checksum generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = 
"c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec"
+"checksum getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = 
"473a1265acc8ff1e808cd0a1af8cee3c2ee5200916058a2ca113c29f2d903571"
 "checksum gio 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = 
"6261b5d34c30c2d59f879e643704cf54cb44731f3a2038000b68790c03e360e3"
 "checksum gio-sys 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = 
"778b856a70a32e2cc5dd5cc7fa1b0c4b6df924fdf5c82984bc28f30565657cfe"
-"checksum glib 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = 
"91a70db179515473b57aaff8b879167f1f8460bc5523e97beacf6d1026a8b99d"
+"checksum glib 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = 
"be27232841baa43e0fd5ae003f7941925735b2f733a336dc75f07b9eff415e7b"
 "checksum glib-sys 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = 
"4b86a9169fbc9cf9a0ef315039c2304b09d5c575c5fde7defba3576a0311b863"
 "checksum gobject-sys 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = 
"61d55bc9202447ca776f6ad0048c36e3312010f66f82ab478e97513e93f3604b"
 "checksum idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = 
"02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9"
@@ -1351,26 +1437,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index";
 "checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = 
"501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f"
 "checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = 
"a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a"
 "checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = 
"e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
-"checksum libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)" = 
"34fcd2c08d2f832f376f4173a231990fa5aef4e99fb569867318a227ef4c06ba"
+"checksum libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)" = 
"1a31a0627fdf1f6a39ec0dd577e101440b7db22672c0901fe00a9a6fbb5c24e8"
 "checksum libm 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = 
"7fc7aa29613bd6a620df431842069224d8bc9011086b1db4c0e0cd47fa03ec9a"
 "checksum locale_config 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = 
"08d2c35b16f4483f6c26f0e4e9550717a2f6575bcd6f12a53ff0c490a94a6934"
 "checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = 
"14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7"
 "checksum mac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = 
"c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4"
 "checksum malloc_buf 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = 
"62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb"
-"checksum markup5ever 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = 
"65381d9d47506b8592b97c4efd936afcf673b09b059f2bef39c7211ee78b9d03"
+"checksum markup5ever 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = 
"aae38d669396ca9b707bfc3db254bc382ddb94f57cc5c235f34623a669a01dab"
 "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = 
"7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08"
-"checksum matrixmultiply 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = 
"dcfed72d871629daa12b25af198f110e8095d7650f5f4c61c5bac28364604f9b"
+"checksum matrixmultiply 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = 
"d4f7ec66360130972f34830bfad9ef05c6610a43938a467bcc9ab9369ab3478f"
 "checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = 
"88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e"
 "checksum memoffset 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = 
"ce6075db033bbbb7ee5a0bbd3a3186bbae616f57fb001c485c7ff77955f8177f"
 "checksum nalgebra 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)" = 
"aaa9fddbc34c8c35dd2108515587b8ce0cab396f17977b8c738568e4edb521a2"
 "checksum new_debug_unreachable 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = 
"f40f005c60db6e03bae699e414c58bf9aa7ea02a2d0b9bfbcf19286cc4c82b30"
-"checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = 
"2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945"
+"checksum nodrop 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = 
"72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb"
 "checksum num-complex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = 
"fcb0cf31fb3ff77e6d2a6ebd6800df7fdcd106f2ad89113c9130bcd07f93dffc"
 "checksum num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = 
"b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09"
 "checksum num-rational 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = 
"f2885278d5fe2adc2f75ced642d52d879bffaceb5a2e0b1d4309ffdfb239b454"
 "checksum num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = 
"6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32"
 "checksum num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = 
"bcef43580c035376c0705c42792c294b66974abbfd2789b511784023f71f3273"
-"checksum objc 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = 
"31d20fd2b37e07cf5125be68357b588672e8cefe9a96f8c17a9d46053b3e590d"
+"checksum objc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = 
"915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1"
 "checksum objc-foundation 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = 
"1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9"
 "checksum objc_id 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = 
"c92d4ddb4bd7b50d730c215ff871754d0da6b2178849f8a2a2ab69712d0c073b"
 "checksum pango 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = 
"393fa071b144f8ffb83ede273758983cf414ca3c0b1d2a5a9ce325b3ba3dd786"
@@ -1379,28 +1465,36 @@ source = "registry+https://github.com/rust-lang/crates.io-index";
 "checksum pangocairo-sys 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = 
"bd3ef177ef222904c6cafd94ddca16db24e6287089b796dd9912f99a139006e3"
 "checksum percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = 
"d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
 "checksum phf 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = 
"b3da44b85f8e8dfaec21adae67f95d93244b2ecf6ad2a692320598dcc8e6dd18"
+"checksum phf 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = 
"3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12"
 "checksum phf_codegen 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = 
"b03e85129e324ad4166b06b2c7491ae27fe3ec353af72e72cd1654c7225d517e"
+"checksum phf_codegen 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = 
"cbffee61585b0411840d3ece935cce9cb6321f01c45477d30066498cd5e1a815"
 "checksum phf_generator 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = 
"09364cc93c159b8b06b1f4dd8a4398984503483891b0c26b867cf431fb132662"
+"checksum phf_generator 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = 
"17367f0cc86f2d25802b2c26ee58a7b23faeccf78a396094c13dced0d0182526"
 "checksum phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = 
"234f71a15de2288bcb7e3b6515828d22af7ec8598ee6d24c3b526fa0a80b67a0"
+"checksum phf_shared 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = 
"c00cf8b9eafe68dde5e9eaa2cef8ee84a9336a47d566ec55ca16589633b65af7"
 "checksum pkg-config 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)" = 
"72d5370d90f49f70bd033c3d75e87fc529fbfff9d6f7cccef07d6170079d91ea"
+"checksum ppv-lite86 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = 
"74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b"
 "checksum precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = 
"925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
-"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = 
"cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759"
-"checksum proc-macro2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = 
"e98a83a9f9b331f54b924e68a66acb1bb35cb01fb0a23645139967abefb697e8"
+"checksum proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = 
"9c9e470a8dc4aeae2dee2f335e8f533e2d4b347e1434e5671afc49b054592f27"
 "checksum procedural-masquerade 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = 
"9a1574a51c3fd37b26d2c0032b649d08a7d51d4cca9c41bbc5bf7118fa4509d0"
-"checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = 
"6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1"
 "checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = 
"053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe"
 "checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = 
"6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca"
+"checksum rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = 
"3ae1b169243eaf61759b8475a998f0a385e42042370f3a7dbaf35246eacc8412"
 "checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = 
"556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef"
+"checksum rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = 
"03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853"
 "checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = 
"7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
 "checksum rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = 
"9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
+"checksum rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = 
"90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
 "checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = 
"7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4"
+"checksum rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = 
"ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
 "checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = 
"ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08"
 "checksum rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = 
"1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b"
 "checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = 
"7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071"
 "checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = 
"abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44"
+"checksum rand_pcg 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = 
"16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429"
 "checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = 
"cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c"
 "checksum rand_xoshiro 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = 
"03b418169fb9c46533f326efd6eed2576699c44ca92d3052a066214a8d828929"
-"checksum rawpointer 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = 
"ebac11a9d2e11f2af219b8b8d833b76b1ea0e054aa0e8d8e9e4cbde353bdf019"
+"checksum rawpointer 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = 
"60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3"
 "checksum rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = 
"83a27732a533a1be0a0035a111fe76db89ad312f6f0347004c220c57f209a123"
 "checksum rayon-core 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = 
"98dcf634205083b17d0861252431eb2acbfb698ab7478a2d20de07954f47ec7b"
 "checksum rctree 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = 
"be9e29cb19c8fe84169fcb07f8f11e66bc9e6e0280efd4715c54818296f8a4a8"
@@ -1409,19 +1503,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index";
 "checksum regex-automata 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = 
"92b73c2a1770c255c240eaa4ee600df1704a38dc3feaa6e949e7fcd4f8dc09f9"
 "checksum regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = 
"11a7e20d1cce64ef2fed88b66d347f88bd9babb82845b2b858f3edbf59a4f716"
 "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = 
"138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
-"checksum ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = 
"c92464b447c0ee8c4fb3824ecc8383b81717b9f1e74ba2e72540aef7b9f82997"
+"checksum ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = 
"bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8"
 "checksum same-file 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = 
"585e8ddcedc187886a30fa705c47985c3fa88d06624095856b36ca0b82ff4421"
 "checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = 
"b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d"
 "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = 
"1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
 "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = 
"388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
-"checksum serde 1.0.100 (registry+https://github.com/rust-lang/crates.io-index)" = 
"f4473e8506b213730ff2061073b48fa51dcc66349219e2e7c5608f0296a1d95a"
-"checksum serde_derive 1.0.100 (registry+https://github.com/rust-lang/crates.io-index)" = 
"11e410fde43e157d789fc290d26bc940778ad0fdd47836426fbac36573710dbb"
-"checksum serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)" = 
"051c49229f282f7c6f3813f8286cc1e3323e8051823fce42c7ea80fe13521704"
+"checksum serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)" = 
"9796c9b7ba2ffe7a9ce53c2287dfc48080f4b2b362fcc245a259b3a7201119dd"
+"checksum serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)" = 
"4b133a43a1ecd55d4086bd5b4dc6c1751c68b1bfbeba7a5040442022c7e7c02e"
+"checksum serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)" = 
"2f72eb2a68a7dc3f9a691bfda9305a1c017a6215e5a4545c258500d2099a37c2"
 "checksum siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = 
"0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac"
+"checksum siphasher 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = 
"83da420ee8d1a89e640d0948c646c1c088758d3a3c538f943bfa97bdac17929d"
 "checksum smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = 
"ab606a9c5e214920bb66c458cd7be8ef094f813f20fe77a54cc7dbfff220d4b7"
-"checksum string_cache 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = 
"25d70109977172b127fe834e5449e5ab1740b9ba49fa18a2020f509174f25423"
-"checksum string_cache_codegen 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = 
"1eea1eee654ef80933142157fdad9dd8bc43cf7c74e999e369263496f04ff4da"
-"checksum string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = 
"b1884d1bc09741d466d9b14e6d37ac89d6909cbcac41dd9ae982d4d063bbedfc"
+"checksum string_cache 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = 
"2940c75beb4e3bf3a494cef919a747a2cb81e52571e212bfbd185074add7208a"
+"checksum string_cache_codegen 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = 
"f24c8e5e19d22a726626f1a5e16fe15b132dcf21d10177fa5a45ce7962996b97"
 "checksum syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = 
"66850e97125af79138385e9b88339cbcd037e3f28ceab8c5ad98e64f0f1f80bf"
 "checksum tendril 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = 
"707feda9f2582d5d680d733e38755547a3e8fb471e7ba11452ecfd9ce93a5d3b"
 "checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = 
"d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
@@ -1431,11 +1525,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index";
 "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = 
"49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
 "checksum unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = 
"141339a08b982d942be2ca06ff8b076563cbe223d1befd5450716790d44e2426"
 "checksum unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = 
"7007dbd421b92cc6e28410fe7362e2e0a2503394908f417b68ec8d1c364c4e20"
-"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = 
"fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
 "checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = 
"826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
 "checksum url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = 
"75b414f6c464c879d7f9babf951f23bc3743fb7313c081b2e6ca719067ea9d61"
 "checksum utf-8 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)" = 
"05e42f7c18b8f902290b009cde6d651262f956c98bc51bca4cd1d511c9cd85c7"
 "checksum walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = 
"9658c94fa8b940eab2250bd5a457f9c48b748420d71293b165c8cdbe2f55f71e"
+"checksum wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = 
"b89c3ce4ce14bdc6fb6beaf9ec7928ca331de5df7e5ea278375642a2f478570d"
 "checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = 
"8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
 "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = 
"ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
 "checksum winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = 
"7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9"
diff --git a/rsvg_internals/Cargo.toml b/rsvg_internals/Cargo.toml
index a267813d..c87f1fd6 100644
--- a/rsvg_internals/Cargo.toml
+++ b/rsvg_internals/Cargo.toml
@@ -25,7 +25,7 @@ language-tags = "0.2.2"
 lazy_static = "1.0.0"
 libc = "0.2"
 locale_config = "*" # recommended explicitly by locale_config's README.md
-markup5ever = "0.9"
+markup5ever = "0.10"
 nalgebra = "0.18"
 num-traits = "0.2"
 pango = "0.7.0"
diff --git a/rsvg_internals/src/clip_path.rs b/rsvg_internals/src/clip_path.rs
index f611fb19..f2514ef2 100644
--- a/rsvg_internals/src/clip_path.rs
+++ b/rsvg_internals/src/clip_path.rs
@@ -1,5 +1,5 @@
 use cairo;
-use markup5ever::local_name;
+use markup5ever::{expanded_name, local_name, namespace_url, ns};
 
 use crate::bbox::BoundingBox;
 use crate::coord_units::CoordUnits;
@@ -70,8 +70,8 @@ impl NodeClipPath {
 impl NodeTrait for NodeClipPath {
     fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
         for (attr, value) in pbag.iter() {
-            match attr {
-                local_name!("clipPathUnits") => self.units = attr.parse(value)?,
+            match attr.expanded() {
+                expanded_name!(svg "clipPathUnits") => self.units = attr.parse(value)?,
                 _ => (),
             }
         }
diff --git a/rsvg_internals/src/create_node.rs b/rsvg_internals/src/create_node.rs
index 56fee676..cdbb6b51 100644
--- a/rsvg_internals/src/create_node.rs
+++ b/rsvg_internals/src/create_node.rs
@@ -1,5 +1,5 @@
 use lazy_static::lazy_static;
-use markup5ever::{local_name, namespace_url, ns, LocalName, Prefix, QualName};
+use markup5ever::{expanded_name, local_name, namespace_url, ns, QualName};
 use std::collections::HashMap;
 
 use crate::clip_path::NodeClipPath;
@@ -42,7 +42,7 @@ use crate::text::{NodeTRef, NodeTSpan, NodeText};
 
 macro_rules! n {
     ($name:ident, $node_type:ident, $node_trait:ty) => {
-        pub fn $name(element_name: QualName, id: Option<&str>, class: Option<&str>) -> RsvgNode {
+        pub fn $name(element_name: &QualName, id: Option<&str>, class: Option<&str>) -> RsvgNode {
             RsvgNode::new(NodeData::new(
                 NodeType::$node_type,
                 element_name,
@@ -111,15 +111,23 @@ mod creators {
     n!(create_turbulence,                FeTurbulence,               Turbulence);
     n!(create_use,                       Use,                        NodeUse);
 
-    // hack to make multiImage sort-of work
+    /* Hack to make multiImage sort-of work
+     *
+     * disabled for now, as markup5ever doesn't have local names for
+     * multiImage, subImage, subImageRef.  Maybe we can just... create them ourselves?
+     *
+     * Is multiImage even in SVG2?
+     */
+    /*
     n!(create_multi_image,               Switch,                     NodeSwitch);
     n!(create_sub_image,                 Group,                      NodeGroup);
     n!(create_sub_image_ref,             Image,                      NodeImage);
+    */
 }
 
 use creators::*;
 
-type NodeCreateFn = fn(element_name: QualName, id: Option<&str>, class: Option<&str>) -> RsvgNode;
+type NodeCreateFn = fn(element_name: &QualName, id: Option<&str>, class: Option<&str>) -> RsvgNode;
 
 macro_rules! c {
     ($hashset:expr, $str_name:expr, $supports_class:expr, $fn_name:ident) => {
@@ -192,7 +200,7 @@ lazy_static! {
         /* c!(h, "metadata",         false, ); */
         /* c!(h, "missing-glyph",    true,  ); */
         /* c!(h, "mpath",            false, ); */
-        c!(h, "multiImage",          false, create_multi_image);
+        /* c!(h, "multiImage",          false, create_multi_image); */
         c!(h, "path",                true,  create_path);
         c!(h, "pattern",             true,  create_pattern);
         c!(h, "polygon",             true,  create_polygon);
@@ -203,8 +211,8 @@ lazy_static! {
         /* c!(h, "set",              false, ); */
         c!(h, "stop",                true,  create_stop);
         c!(h, "style",               false, create_style);
-        c!(h, "subImage",            false, create_sub_image);
-        c!(h, "subImageRef",         false, create_sub_image_ref);
+        /* c!(h, "subImage",            false, create_sub_image); */
+        /* c!(h, "subImageRef",         false, create_sub_image_ref); */
         c!(h, "svg",                 true,  create_svg);
         c!(h, "switch",              true,  create_switch);
         c!(h, "symbol",              true,  create_symbol);
@@ -221,7 +229,7 @@ lazy_static! {
 }
 
 pub fn create_node_and_register_id(
-    name: &str,
+    name: &QualName,
     pbag: &PropertyBag,
     ids: &mut HashMap<String, RsvgNode>,
 ) -> RsvgNode {
@@ -229,30 +237,32 @@ pub fn create_node_and_register_id(
     let mut class = None;
 
     for (attr, value) in pbag.iter() {
-        match attr {
-            local_name!("id") => id = Some(value),
-            local_name!("class") => class = Some(value),
+        match attr.expanded() {
+            expanded_name!(svg "id") => id = Some(value),
+            expanded_name!(svg "class") => class = Some(value),
             _ => (),
         }
     }
 
-    let (supports_class, create_fn, prefix, namespace) = match NODE_CREATORS.get(name) {
-        // hack in the SVG namespace for supported element names
-        Some(&(supports_class, create_fn)) => (supports_class, create_fn, Some("svg"), ns!(svg)),
+    let (supports_class, create_fn) = if name.ns == ns!(svg) {
+        match NODE_CREATORS.get(name.local.as_ref()) {
+            // hack in the SVG namespace for supported element names
+            Some(&(supports_class, create_fn)) => (supports_class, create_fn),
 
-        // Whenever we encounter a node we don't understand, represent it as a
-        // non-rendering node.  This is like a group, but it doesn't do any rendering of
-        // children.  The effect is that we will ignore all children of unknown elements.
-        None => (true, create_non_rendering as NodeCreateFn, None, ns!()),
+            // Whenever we encounter a node we don't understand, represent it as a
+            // non-rendering node.  This is like a group, but it doesn't do any rendering of
+            // children.  The effect is that we will ignore all children of unknown elements.
+            None => (true, create_non_rendering as NodeCreateFn),
+        }
+    } else {
+        (true, create_non_rendering as NodeCreateFn)
     };
 
-    let element_name = QualName::new(prefix.map(Prefix::from), namespace, LocalName::from(name));
-
     if !supports_class {
         class = None;
     };
 
-    let node = create_fn(element_name, id, class);
+    let node = create_fn(name, id, class);
 
     if let Some(id) = id {
         // This is so we don't overwrite an existing id
diff --git a/rsvg_internals/src/css.rs b/rsvg_internals/src/css.rs
index 2bb4a3b9..258668ad 100644
--- a/rsvg_internals/src/css.rs
+++ b/rsvg_internals/src/css.rs
@@ -13,7 +13,7 @@ use std::ptr;
 use std::str;
 
 use libc;
-use markup5ever::LocalName;
+use markup5ever::{namespace_url, ns, LocalName, QualName};
 use url::Url;
 
 use glib::translate::*;
@@ -29,7 +29,7 @@ use crate::util::utf8_cstr;
 
 /// A parsed CSS declaration (`name: value [!important]`)
 pub struct Declaration {
-    pub attribute: LocalName,
+    pub attribute: QualName,
     pub property: ParsedProperty,
     pub important: bool,
 }
@@ -37,7 +37,7 @@ pub struct Declaration {
 #[derive(Default)]
 pub struct DeclarationList {
     // Maps property_name -> Declaration
-    declarations: HashMap<LocalName, Declaration>,
+    declarations: HashMap<QualName, Declaration>,
 }
 
 pub struct DeclParser;
@@ -51,7 +51,7 @@ impl<'i> DeclarationParser<'i> for DeclParser {
         name: CowRcStr<'i>,
         input: &mut Parser<'i, 't>,
     ) -> Result<Declaration, cssparser::ParseError<'i, ValueErrorKind>> {
-        let attribute = LocalName::from(name.as_ref());
+        let attribute = QualName::new(None, ns!(svg), LocalName::from(name.as_ref()));
         let property = parse_attribute_value_into_parsed_property(&attribute, input, true)
             .map_err(|e| input.new_custom_error(e))?;
 
@@ -110,7 +110,7 @@ impl DeclarationList {
     }
 }
 
-pub struct DeclarationListIter<'a>(HashMapIter<'a, LocalName, Declaration>);
+pub struct DeclarationListIter<'a>(HashMapIter<'a, QualName, Declaration>);
 
 impl<'a> Iterator for DeclarationListIter<'a> {
     type Item = &'a Declaration;
@@ -390,7 +390,7 @@ unsafe extern "C" fn css_property(
 
                 let important = from_glib(a_is_important);
 
-                let attribute = LocalName::from(prop_name);
+                let attribute = QualName::new(None, ns!(svg), LocalName::from(prop_name));
 
                 let mut input = ParserInput::new(&prop_value);
                 let mut parser = Parser::new(&mut input);
diff --git a/rsvg_internals/src/error.rs b/rsvg_internals/src/error.rs
index 05c90f99..ee84801a 100644
--- a/rsvg_internals/src/error.rs
+++ b/rsvg_internals/src/error.rs
@@ -8,7 +8,7 @@ use glib::error::ErrorDomain;
 use glib::translate::*;
 use glib_sys;
 use libc;
-use markup5ever::LocalName;
+use markup5ever::QualName;
 
 use crate::allowed_url::Fragment;
 use crate::node::RsvgNode;
@@ -30,26 +30,26 @@ pub enum ValueErrorKind {
 /// A complete error for an attribute and its erroneous value
 #[derive(Debug, Clone, PartialEq)]
 pub struct NodeError {
-    attr: LocalName,
+    attr: QualName,
     err: ValueErrorKind,
 }
 
 impl NodeError {
-    pub fn parse_error(attr: LocalName, error: ParseError) -> NodeError {
+    pub fn parse_error(attr: QualName, error: ParseError) -> NodeError {
         NodeError {
             attr,
             err: ValueErrorKind::Parse(error),
         }
     }
 
-    pub fn value_error(attr: LocalName, description: &str) -> NodeError {
+    pub fn value_error(attr: QualName, description: &str) -> NodeError {
         NodeError {
             attr,
             err: ValueErrorKind::Value(description.to_string()),
         }
     }
 
-    pub fn attribute_error(attr: LocalName, error: ValueErrorKind) -> NodeError {
+    pub fn attribute_error(attr: QualName, error: ValueErrorKind) -> NodeError {
         NodeError { attr, err: error }
     }
 }
@@ -72,14 +72,14 @@ impl fmt::Display for NodeError {
             ValueErrorKind::Parse(ref n) => write!(
                 f,
                 "error parsing value for attribute \"{}\": {}",
-                self.attr.to_string(),
+                self.attr.local.to_string(),
                 n.display
             ),
 
             ValueErrorKind::Value(ref s) => write!(
                 f,
                 "invalid value for attribute \"{}\": {}",
-                self.attr.to_string(),
+                self.attr.local.to_string(),
                 s
             ),
         }
@@ -151,7 +151,7 @@ impl fmt::Display for AcquireError {
 
 /// Helper for converting `Result<O, E>` into `Result<O, NodeError>`
 ///
-/// A `NodeError` requires a `LocalName` that corresponds to the attribute to which the
+/// A `NodeError` requires a `QualName` that corresponds to the attribute to which the
 /// error refers, plus the actual `ValueErrorKind` that describes the error.  However,
 /// parsing functions for attribute value types will want to return their own kind of
 /// error, instead of `ValueErrorKind`.  If that particular error type has an `impl
@@ -171,11 +171,11 @@ impl fmt::Display for AcquireError {
 /// The call to `.attribute(attr)` converts the `Result` from `parse_foo()` into a full
 /// `NodeError` with the provided `attr`.
 pub trait AttributeResultExt<O, E> {
-    fn attribute(self, attr: LocalName) -> Result<O, NodeError>;
+    fn attribute(self, attr: QualName) -> Result<O, NodeError>;
 }
 
 impl<O, E: Into<ValueErrorKind>> AttributeResultExt<O, E> for Result<O, E> {
-    fn attribute(self, attr: LocalName) -> Result<O, NodeError> {
+    fn attribute(self, attr: QualName) -> Result<O, NodeError> {
         self.map_err(|e| e.into())
             .map_err(|e| NodeError::attribute_error(attr, e))
     }
diff --git a/rsvg_internals/src/filters/blend.rs b/rsvg_internals/src/filters/blend.rs
index 34cbe047..03a91477 100755
--- a/rsvg_internals/src/filters/blend.rs
+++ b/rsvg_internals/src/filters/blend.rs
@@ -1,5 +1,5 @@
 use cairo;
-use markup5ever::{local_name, LocalName};
+use markup5ever::{expanded_name, local_name, namespace_url, ns, QualName};
 
 use crate::drawing_ctx::DrawingCtx;
 use crate::error::NodeError;
@@ -59,11 +59,11 @@ impl NodeTrait for Blend {
         self.base.set_atts(parent, pbag)?;
 
         for (attr, value) in pbag.iter() {
-            match attr {
-                local_name!("in2") => {
+            match attr.expanded() {
+                expanded_name!(svg "in2") => {
                     self.in2 = Some(Input::parse(attr, value)?);
                 }
-                local_name!("mode") => self.mode = Mode::parse(attr, value)?,
+                expanded_name!(svg "mode") => self.mode = Mode::parse(attr, value)?,
                 _ => (),
             }
         }
@@ -133,7 +133,7 @@ impl Filter for Blend {
 }
 
 impl Mode {
-    fn parse(attr: LocalName, s: &str) -> Result<Self, NodeError> {
+    fn parse(attr: QualName, s: &str) -> Result<Self, NodeError> {
         match s {
             "normal" => Ok(Mode::Normal),
             "multiply" => Ok(Mode::Multiply),
diff --git a/rsvg_internals/src/filters/color_matrix.rs b/rsvg_internals/src/filters/color_matrix.rs
index c6228d92..36596c36 100644
--- a/rsvg_internals/src/filters/color_matrix.rs
+++ b/rsvg_internals/src/filters/color_matrix.rs
@@ -1,5 +1,5 @@
 use cairo::{self, ImageSurface};
-use markup5ever::{local_name, LocalName};
+use markup5ever::{expanded_name, local_name, namespace_url, ns, QualName};
 use nalgebra::{Matrix3, Matrix4x5, Matrix5, Vector5};
 
 use crate::drawing_ctx::DrawingCtx;
@@ -9,10 +9,7 @@ use crate::number_list::{NumberList, NumberListError, NumberListLength};
 use crate::parsers::{self, ParseError};
 use crate::property_bag::PropertyBag;
 use crate::surface_utils::{
-    iterators::Pixels,
-    shared_surface::SharedImageSurface,
-    ImageSurfaceDataExt,
-    Pixel,
+    iterators::Pixels, shared_surface::SharedImageSurface, ImageSurfaceDataExt, Pixel,
 };
 use crate::util::clamp;
 
@@ -53,7 +50,10 @@ impl NodeTrait for ColorMatrix {
 
         // First, determine the operation type.
         let mut operation_type = OperationType::Matrix;
-        for (attr, value) in pbag.iter().filter(|(attr, _)| *attr == local_name!("type")) {
+        for (attr, value) in pbag
+            .iter()
+            .filter(|(attr, _)| attr.expanded() == expanded_name!(svg "type"))
+        {
             operation_type = OperationType::parse(attr, value)?;
         }
 
@@ -73,7 +73,7 @@ impl NodeTrait for ColorMatrix {
         } else {
             for (attr, value) in pbag
                 .iter()
-                .filter(|(attr, _)| *attr == local_name!("values"))
+                .filter(|(attr, _)| attr.expanded() == expanded_name!(svg "values"))
             {
                 let new_matrix = match operation_type {
                     OperationType::LuminanceToAlpha => unreachable!(),
@@ -227,7 +227,7 @@ impl Filter for ColorMatrix {
 }
 
 impl OperationType {
-    fn parse(attr: LocalName, s: &str) -> Result<Self, NodeError> {
+    fn parse(attr: QualName, s: &str) -> Result<Self, NodeError> {
         match s {
             "matrix" => Ok(OperationType::Matrix),
             "saturate" => Ok(OperationType::Saturate),
diff --git a/rsvg_internals/src/filters/component_transfer.rs 
b/rsvg_internals/src/filters/component_transfer.rs
index 7bd37669..368403b2 100644
--- a/rsvg_internals/src/filters/component_transfer.rs
+++ b/rsvg_internals/src/filters/component_transfer.rs
@@ -1,7 +1,7 @@
 use std::cmp::min;
 
 use cairo::{self, ImageSurface};
-use markup5ever::{local_name, LocalName};
+use markup5ever::{expanded_name, local_name, namespace_url, ns, QualName};
 
 use crate::drawing_ctx::DrawingCtx;
 use crate::error::{AttributeResultExt, NodeError};
@@ -64,7 +64,7 @@ enum FunctionType {
 }
 
 impl FunctionType {
-    fn parse(attr: LocalName, s: &str) -> Result<Self, NodeError> {
+    fn parse(attr: QualName, s: &str) -> Result<Self, NodeError> {
         match s {
             "identity" => Ok(FunctionType::Identity),
             "table" => Ok(FunctionType::Table),
@@ -212,11 +212,11 @@ macro_rules! func_x {
                 pbag: &PropertyBag<'_>,
             ) -> NodeResult {
                 for (attr, value) in pbag.iter() {
-                    match attr {
-                        local_name!("type") => {
+                    match attr.expanded() {
+                        expanded_name!(svg "type") => {
                             self.function_type = FunctionType::parse(attr, value)?
                         }
-                        local_name!("tableValues") => {
+                        expanded_name!(svg "tableValues") => {
                             let NumberList(v) =
                                 NumberList::parse_str(value, NumberListLength::Unbounded).map_err(
                                     |err| {
@@ -229,19 +229,19 @@ macro_rules! func_x {
                                 )?;
                             self.table_values = v;
                         }
-                        local_name!("slope") => {
+                        expanded_name!(svg "slope") => {
                             self.slope = parsers::number(value).attribute(attr)?
                         }
-                        local_name!("intercept") => {
+                        expanded_name!(svg "intercept") => {
                             self.intercept = parsers::number(value).attribute(attr)?
                         }
-                        local_name!("amplitude") => {
+                        expanded_name!(svg "amplitude") => {
                             self.amplitude = parsers::number(value).attribute(attr)?
                         }
-                        local_name!("exponent") => {
+                        expanded_name!(svg "exponent") => {
                             self.exponent = parsers::number(value).attribute(attr)?
                         }
-                        local_name!("offset") => {
+                        expanded_name!(svg "offset") => {
                             self.offset = parsers::number(value).attribute(attr)?
                         }
                         _ => (),
diff --git a/rsvg_internals/src/filters/composite.rs b/rsvg_internals/src/filters/composite.rs
index 2786899f..a3033fde 100644
--- a/rsvg_internals/src/filters/composite.rs
+++ b/rsvg_internals/src/filters/composite.rs
@@ -1,6 +1,6 @@
 use cairo::{self, ImageSurface};
 use cssparser::{CowRcStr, Parser, Token};
-use markup5ever::local_name;
+use markup5ever::{expanded_name, local_name, namespace_url, ns};
 
 use crate::drawing_ctx::DrawingCtx;
 use crate::error::{AttributeResultExt, ValueErrorKind};
@@ -65,13 +65,13 @@ impl NodeTrait for Composite {
         self.base.set_atts(parent, pbag)?;
 
         for (attr, value) in pbag.iter() {
-            match attr {
-                local_name!("in2") => self.in2 = Some(Input::parse(attr, value)?),
-                local_name!("operator") => self.operator = attr.parse(value)?,
-                local_name!("k1") => self.k1 = parsers::number(value).attribute(attr)?,
-                local_name!("k2") => self.k2 = parsers::number(value).attribute(attr)?,
-                local_name!("k3") => self.k3 = parsers::number(value).attribute(attr)?,
-                local_name!("k4") => self.k4 = parsers::number(value).attribute(attr)?,
+            match attr.expanded() {
+                expanded_name!(svg "in2") => self.in2 = Some(Input::parse(attr, value)?),
+                expanded_name!(svg "operator") => self.operator = attr.parse(value)?,
+                expanded_name!(svg "k1") => self.k1 = parsers::number(value).attribute(attr)?,
+                expanded_name!(svg "k2") => self.k2 = parsers::number(value).attribute(attr)?,
+                expanded_name!(svg "k3") => self.k3 = parsers::number(value).attribute(attr)?,
+                expanded_name!(svg "k4") => self.k4 = parsers::number(value).attribute(attr)?,
                 _ => (),
             }
         }
diff --git a/rsvg_internals/src/filters/convolve_matrix.rs b/rsvg_internals/src/filters/convolve_matrix.rs
index 4ba955ca..8ff9519a 100644
--- a/rsvg_internals/src/filters/convolve_matrix.rs
+++ b/rsvg_internals/src/filters/convolve_matrix.rs
@@ -1,5 +1,5 @@
 use cairo::{self, ImageSurface};
-use markup5ever::{local_name, LocalName};
+use markup5ever::{expanded_name, local_name, namespace_url, ns, QualName};
 use nalgebra::{DMatrix, Dynamic, VecStorage};
 
 use crate::drawing_ctx::DrawingCtx;
@@ -61,8 +61,8 @@ impl NodeTrait for ConvolveMatrix {
         self.base.set_atts(parent, pbag)?;
 
         for (attr, value) in pbag.iter() {
-            match attr {
-                local_name!("order") => {
+            match attr.expanded() {
+                expanded_name!(svg "order") => {
                     self.order = parsers::integer_optional_integer(value)
                         .attribute(attr.clone())
                         .and_then(|(x, y)| {
@@ -76,7 +76,7 @@ impl NodeTrait for ConvolveMatrix {
                             }
                         })?
                 }
-                local_name!("divisor") => {
+                expanded_name!(svg "divisor") => {
                     self.divisor = Some(parsers::number(value).attribute(attr.clone()).and_then(
                         |x| {
                             if x != 0.0 {
@@ -87,9 +87,9 @@ impl NodeTrait for ConvolveMatrix {
                         },
                     )?)
                 }
-                local_name!("bias") => self.bias = parsers::number(value).attribute(attr)?,
-                local_name!("edgeMode") => self.edge_mode = EdgeMode::parse(attr, value)?,
-                local_name!("kernelUnitLength") => {
+                expanded_name!(svg "bias") => self.bias = parsers::number(value).attribute(attr)?,
+                expanded_name!(svg "edgeMode") => self.edge_mode = EdgeMode::parse(attr, value)?,
+                expanded_name!(svg "kernelUnitLength") => {
                     self.kernel_unit_length = Some(
                         parsers::number_optional_number(value)
                             .attribute(attr.clone())
@@ -105,7 +105,7 @@ impl NodeTrait for ConvolveMatrix {
                             })?,
                     )
                 }
-                local_name!("preserveAlpha") => {
+                expanded_name!(svg "preserveAlpha") => {
                     self.preserve_alpha = match value {
                         "false" => false,
                         "true" => true,
@@ -123,8 +123,8 @@ impl NodeTrait for ConvolveMatrix {
 
         // target_x and target_y depend on order.
         for (attr, value) in pbag.iter() {
-            match attr {
-                local_name!("targetX") => {
+            match attr.expanded() {
+                expanded_name!(svg "targetX") => {
                     self.target_x = Some(parsers::integer(value).attribute(attr.clone()).and_then(
                         |x| {
                             if x >= 0 && x < self.order.0 as i32 {
@@ -138,7 +138,7 @@ impl NodeTrait for ConvolveMatrix {
                         },
                     )?)
                 }
-                local_name!("targetY") => {
+                expanded_name!(svg "targetY") => {
                     self.target_y = Some(parsers::integer(value).attribute(attr.clone()).and_then(
                         |x| {
                             if x >= 0 && x < self.order.1 as i32 {
@@ -167,7 +167,7 @@ impl NodeTrait for ConvolveMatrix {
         // Finally, parse the kernel matrix.
         for (attr, value) in pbag
             .iter()
-            .filter(|(attr, _)| *attr == local_name!("kernelMatrix"))
+            .filter(|(attr, _)| attr.expanded() == expanded_name!(svg "kernelMatrix"))
         {
             self.kernel_matrix = Some({
                 let number_of_elements = self.order.0 as usize * self.order.1 as usize;
@@ -206,7 +206,7 @@ impl NodeTrait for ConvolveMatrix {
         // kernel_matrix must have been specified.
         if self.kernel_matrix.is_none() {
             return Err(NodeError::value_error(
-                local_name!("kernelMatrix"),
+                QualName::new(None, ns!(svg), local_name!("kernelMatrix")),
                 "the value must be set",
             ));
         }
@@ -365,7 +365,7 @@ impl Filter for ConvolveMatrix {
 }
 
 impl EdgeMode {
-    fn parse(attr: LocalName, s: &str) -> Result<Self, NodeError> {
+    fn parse(attr: QualName, s: &str) -> Result<Self, NodeError> {
         match s {
             "duplicate" => Ok(EdgeMode::Duplicate),
             "wrap" => Ok(EdgeMode::Wrap),
diff --git a/rsvg_internals/src/filters/displacement_map.rs b/rsvg_internals/src/filters/displacement_map.rs
index ea491613..e4809e2f 100644
--- a/rsvg_internals/src/filters/displacement_map.rs
+++ b/rsvg_internals/src/filters/displacement_map.rs
@@ -1,5 +1,5 @@
 use cairo::{self, ImageSurface};
-use markup5ever::{local_name, LocalName};
+use markup5ever::{expanded_name, local_name, namespace_url, ns, QualName};
 
 use crate::drawing_ctx::DrawingCtx;
 use crate::error::{AttributeResultExt, NodeError};
@@ -50,13 +50,13 @@ impl NodeTrait for DisplacementMap {
         self.base.set_atts(parent, pbag)?;
 
         for (attr, value) in pbag.iter() {
-            match attr {
-                local_name!("in2") => self.in2 = Some(Input::parse(attr, value)?),
-                local_name!("scale") => self.scale = parsers::number(value).attribute(attr)?,
-                local_name!("xChannelSelector") => {
+            match attr.expanded() {
+                expanded_name!(svg "in2") => self.in2 = Some(Input::parse(attr, value)?),
+                expanded_name!(svg "scale") => self.scale = parsers::number(value).attribute(attr)?,
+                expanded_name!(svg "xChannelSelector") => {
                     self.x_channel_selector = ColorChannel::parse(attr, value)?
                 }
-                local_name!("yChannelSelector") => {
+                expanded_name!(svg "yChannelSelector") => {
                     self.y_channel_selector = ColorChannel::parse(attr, value)?
                 }
                 _ => (),
@@ -144,7 +144,7 @@ impl Filter for DisplacementMap {
 }
 
 impl ColorChannel {
-    fn parse(attr: LocalName, s: &str) -> Result<Self, NodeError> {
+    fn parse(attr: QualName, s: &str) -> Result<Self, NodeError> {
         match s {
             "R" => Ok(ColorChannel::R),
             "G" => Ok(ColorChannel::G),
diff --git a/rsvg_internals/src/filters/gaussian_blur.rs b/rsvg_internals/src/filters/gaussian_blur.rs
index 61e75971..b64d45b5 100644
--- a/rsvg_internals/src/filters/gaussian_blur.rs
+++ b/rsvg_internals/src/filters/gaussian_blur.rs
@@ -1,7 +1,7 @@
 use std::cmp::min;
 use std::f64;
 
-use markup5ever::local_name;
+use markup5ever::{expanded_name, local_name, namespace_url, ns};
 use nalgebra::{DMatrix, Dynamic, VecStorage};
 
 use crate::drawing_ctx::DrawingCtx;
@@ -47,8 +47,8 @@ impl NodeTrait for GaussianBlur {
         self.base.set_atts(parent, pbag)?;
 
         for (attr, value) in pbag.iter() {
-            match attr {
-                local_name!("stdDeviation") => {
+            match attr.expanded() {
+                expanded_name!(svg "stdDeviation") => {
                     self.std_deviation = parsers::number_optional_number(value)
                         .attribute(attr.clone())
                         .and_then(|(x, y)| {
diff --git a/rsvg_internals/src/filters/image.rs b/rsvg_internals/src/filters/image.rs
index a8d69cac..aecaad38 100644
--- a/rsvg_internals/src/filters/image.rs
+++ b/rsvg_internals/src/filters/image.rs
@@ -1,5 +1,5 @@
 use cairo::{self, ImageSurface, Rectangle};
-use markup5ever::local_name;
+use markup5ever::{expanded_name, local_name, namespace_url, ns};
 
 use crate::allowed_url::{Fragment, Href};
 use crate::aspect_ratio::AspectRatio;
@@ -178,11 +178,11 @@ impl NodeTrait for Image {
         self.base.set_atts(parent, pbag)?;
 
         for (attr, value) in pbag.iter() {
-            match attr {
-                local_name!("preserveAspectRatio") => self.aspect = attr.parse(value)?,
+            match attr.expanded() {
+                expanded_name!(svg "preserveAspectRatio") => self.aspect = attr.parse(value)?,
 
                 // "path" is used by some older Adobe Illustrator versions
-                local_name!("xlink:href") | local_name!("path") => {
+                expanded_name!(xlink "href") | expanded_name!(svg "path") => {
                     let href = Href::parse(value).map_err(|_| {
                         NodeError::parse_error(attr, ParseError::new("could not parse href"))
                     })?;
diff --git a/rsvg_internals/src/filters/input.rs b/rsvg_internals/src/filters/input.rs
index 902667a2..70c24a06 100644
--- a/rsvg_internals/src/filters/input.rs
+++ b/rsvg_internals/src/filters/input.rs
@@ -1,4 +1,4 @@
-use markup5ever::LocalName;
+use markup5ever::QualName;
 
 use crate::error::NodeError;
 use crate::parsers::ParseError;
@@ -16,7 +16,7 @@ pub enum Input {
 }
 
 impl Input {
-    pub fn parse(attr: LocalName, s: &str) -> Result<Input, NodeError> {
+    pub fn parse(attr: QualName, s: &str) -> Result<Input, NodeError> {
         match s {
             "SourceGraphic" => Ok(Input::SourceGraphic),
             "SourceAlpha" => Ok(Input::SourceAlpha),
diff --git a/rsvg_internals/src/filters/light/light_source.rs 
b/rsvg_internals/src/filters/light/light_source.rs
index 1665ee79..f78ed065 100644
--- a/rsvg_internals/src/filters/light/light_source.rs
+++ b/rsvg_internals/src/filters/light/light_source.rs
@@ -1,5 +1,5 @@
 use cssparser;
-use markup5ever::local_name;
+use markup5ever::{expanded_name, local_name, namespace_url, ns};
 use nalgebra::Vector3;
 
 use crate::error::AttributeResultExt;
@@ -106,9 +106,9 @@ impl DistantLight {
 impl NodeTrait for DistantLight {
     fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
         for (attr, value) in pbag.iter() {
-            match attr {
-                local_name!("azimuth") => self.azimuth = parsers::number(value).attribute(attr)?,
-                local_name!("elevation") => {
+            match attr.expanded() {
+                expanded_name!(svg "azimuth") => self.azimuth = parsers::number(value).attribute(attr)?,
+                expanded_name!(svg "elevation") => {
                     self.elevation = parsers::number(value).attribute(attr)?
                 }
                 _ => (),
@@ -140,10 +140,10 @@ impl PointLight {
 impl NodeTrait for PointLight {
     fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
         for (attr, value) in pbag.iter() {
-            match attr {
-                local_name!("x") => self.x = parsers::number(value).attribute(attr)?,
-                local_name!("y") => self.y = parsers::number(value).attribute(attr)?,
-                local_name!("z") => self.z = parsers::number(value).attribute(attr)?,
+            match attr.expanded() {
+                expanded_name!(svg "x") => self.x = parsers::number(value).attribute(attr)?,
+                expanded_name!(svg "y") => self.y = parsers::number(value).attribute(attr)?,
+                expanded_name!(svg "z") => self.z = parsers::number(value).attribute(attr)?,
                 _ => (),
             }
         }
@@ -189,23 +189,23 @@ impl SpotLight {
 impl NodeTrait for SpotLight {
     fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
         for (attr, value) in pbag.iter() {
-            match attr {
-                local_name!("x") => self.x = parsers::number(value).attribute(attr)?,
-                local_name!("y") => self.y = parsers::number(value).attribute(attr)?,
-                local_name!("z") => self.z = parsers::number(value).attribute(attr)?,
-                local_name!("pointsAtX") => {
+            match attr.expanded() {
+                expanded_name!(svg "x") => self.x = parsers::number(value).attribute(attr)?,
+                expanded_name!(svg "y") => self.y = parsers::number(value).attribute(attr)?,
+                expanded_name!(svg "z") => self.z = parsers::number(value).attribute(attr)?,
+                expanded_name!(svg "pointsAtX") => {
                     self.points_at_x = parsers::number(value).attribute(attr)?
                 }
-                local_name!("pointsAtY") => {
+                expanded_name!(svg "pointsAtY") => {
                     self.points_at_y = parsers::number(value).attribute(attr)?
                 }
-                local_name!("pointsAtZ") => {
+                expanded_name!(svg "pointsAtZ") => {
                     self.points_at_z = parsers::number(value).attribute(attr)?
                 }
-                local_name!("specularExponent") => {
+                expanded_name!(svg "specularExponent") => {
                     self.specular_exponent = parsers::number(value).attribute(attr)?
                 }
-                local_name!("limitingConeAngle") => {
+                expanded_name!(svg "limitingConeAngle") => {
                     self.limiting_cone_angle = Some(parsers::number(value).attribute(attr)?)
                 }
                 _ => (),
diff --git a/rsvg_internals/src/filters/light/lighting.rs b/rsvg_internals/src/filters/light/lighting.rs
index ffdb8def..115e381b 100644
--- a/rsvg_internals/src/filters/light/lighting.rs
+++ b/rsvg_internals/src/filters/light/lighting.rs
@@ -2,7 +2,7 @@ use std::cmp::max;
 
 use cairo::{self, ImageSurface};
 use cssparser;
-use markup5ever::local_name;
+use markup5ever::{expanded_name, local_name, namespace_url, ns};
 use nalgebra::Vector3;
 use num_traits::identities::Zero;
 use rayon::prelude::*;
@@ -67,11 +67,11 @@ impl Common {
         self.base.set_atts(parent, pbag)?;
 
         for (attr, value) in pbag.iter() {
-            match attr {
-                local_name!("surfaceScale") => {
+            match attr.expanded() {
+                expanded_name!(svg "surfaceScale") => {
                     self.surface_scale = parsers::number(value).attribute(attr)?
                 }
-                local_name!("kernelUnitLength") => {
+                expanded_name!(svg "kernelUnitLength") => {
                     self.kernel_unit_length = Some(
                         parsers::number_optional_number(value)
                             .attribute(attr.clone())
@@ -117,8 +117,8 @@ impl NodeTrait for DiffuseLighting {
         self.common.set_atts(parent, pbag)?;
 
         for (attr, value) in pbag.iter() {
-            match attr {
-                local_name!("diffuseConstant") => {
+            match attr.expanded() {
+                expanded_name!(svg "diffuseConstant") => {
                     self.diffuse_constant = parsers::number(value)
                         .attribute(attr.clone())
                         .and_then(|x| {
@@ -189,8 +189,8 @@ impl NodeTrait for SpecularLighting {
         self.common.set_atts(parent, pbag)?;
 
         for (attr, value) in pbag.iter() {
-            match attr {
-                local_name!("specularConstant") => {
+            match attr.expanded() {
+                expanded_name!(svg "specularConstant") => {
                     self.specular_constant = parsers::number(value)
                         .attribute(attr.clone())
                         .and_then(|x| {
@@ -204,7 +204,7 @@ impl NodeTrait for SpecularLighting {
                             }
                         })?;
                 }
-                local_name!("specularExponent") => {
+                expanded_name!(svg "specularExponent") => {
                     self.specular_exponent = parsers::number(value)
                         .attribute(attr.clone())
                         .and_then(|x| {
diff --git a/rsvg_internals/src/filters/merge.rs b/rsvg_internals/src/filters/merge.rs
index 202068a3..e198f945 100644
--- a/rsvg_internals/src/filters/merge.rs
+++ b/rsvg_internals/src/filters/merge.rs
@@ -1,5 +1,5 @@
 use cairo::{self, ImageSurface};
-use markup5ever::local_name;
+use markup5ever::{expanded_name, local_name, namespace_url, ns};
 
 use crate::drawing_ctx::DrawingCtx;
 use crate::node::{NodeResult, NodeTrait, NodeType, RsvgNode};
@@ -45,8 +45,8 @@ impl NodeTrait for MergeNode {
     #[inline]
     fn set_atts(&mut self, _parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
         for (attr, value) in pbag.iter() {
-            match attr {
-                local_name!("in") => self.in_ = Some(Input::parse(attr, value)?),
+            match attr.expanded() {
+                expanded_name!(svg "in") => self.in_ = Some(Input::parse(attr, value)?),
                 _ => (),
             }
         }
diff --git a/rsvg_internals/src/filters/mod.rs b/rsvg_internals/src/filters/mod.rs
index 777d540a..02b46e2f 100644
--- a/rsvg_internals/src/filters/mod.rs
+++ b/rsvg_internals/src/filters/mod.rs
@@ -2,7 +2,7 @@ use std::ops::Deref;
 use std::time::Instant;
 
 use cairo;
-use markup5ever::local_name;
+use markup5ever::{expanded_name, local_name, namespace_url, ns};
 
 use crate::bbox::BoundingBox;
 use crate::coord_units::CoordUnits;
@@ -161,28 +161,28 @@ impl NodeTrait for Primitive {
         };
 
         for (attr, value) in pbag.iter() {
-            match attr {
-                local_name!("x") => {
+            match attr.expanded() {
+                expanded_name!(svg "x") => {
                     self.x = Some(attr.parse_and_validate(value, check_units_horizontal)?)
                 }
-                local_name!("y") => {
+                expanded_name!(svg "y") => {
                     self.y = Some(attr.parse_and_validate(value, check_units_vertical)?)
                 }
-                local_name!("width") => {
+                expanded_name!(svg "width") => {
                     self.width =
                         Some(attr.parse_and_validate(
                             value,
                             check_units_horizontal_and_ensure_nonnegative,
                         )?)
                 }
-                local_name!("height") => {
+                expanded_name!(svg "height") => {
                     self.height =
                         Some(attr.parse_and_validate(
                             value,
                             check_units_vertical_and_ensure_nonnegative,
                         )?)
                 }
-                local_name!("result") => self.result = Some(value.to_string()),
+                expanded_name!(svg "result") => self.result = Some(value.to_string()),
                 _ => (),
             }
         }
@@ -217,8 +217,8 @@ impl NodeTrait for PrimitiveWithInput {
         self.base.set_atts(parent, pbag)?;
 
         for (attr, value) in pbag.iter() {
-            match attr {
-                local_name!("in") => drop(self.in_ = Some(Input::parse(attr, value)?)),
+            match attr.expanded() {
+                expanded_name!(svg "in") => drop(self.in_ = Some(Input::parse(attr, value)?)),
                 _ => (),
             }
         }
diff --git a/rsvg_internals/src/filters/morphology.rs b/rsvg_internals/src/filters/morphology.rs
index 286c254f..edade0c5 100644
--- a/rsvg_internals/src/filters/morphology.rs
+++ b/rsvg_internals/src/filters/morphology.rs
@@ -1,7 +1,7 @@
 use std::cmp::{max, min};
 
 use cairo::{self, ImageSurface};
-use markup5ever::{local_name, LocalName};
+use markup5ever::{expanded_name, local_name, namespace_url, ns, QualName};
 
 use crate::drawing_ctx::DrawingCtx;
 use crate::error::{AttributeResultExt, NodeError};
@@ -53,9 +53,9 @@ impl NodeTrait for Morphology {
         self.base.set_atts(parent, pbag)?;
 
         for (attr, value) in pbag.iter() {
-            match attr {
-                local_name!("operator") => self.operator = Operator::parse(attr, value)?,
-                local_name!("radius") => {
+            match attr.expanded() {
+                expanded_name!(svg "operator") => self.operator = Operator::parse(attr, value)?,
+                expanded_name!(svg "radius") => {
                     self.radius = parsers::number_optional_number(value)
                         .attribute(attr.clone())
                         .and_then(|(x, y)| {
@@ -161,7 +161,7 @@ impl Filter for Morphology {
 }
 
 impl Operator {
-    fn parse(attr: LocalName, s: &str) -> Result<Self, NodeError> {
+    fn parse(attr: QualName, s: &str) -> Result<Self, NodeError> {
         match s {
             "erode" => Ok(Operator::Erode),
             "dilate" => Ok(Operator::Dilate),
diff --git a/rsvg_internals/src/filters/node.rs b/rsvg_internals/src/filters/node.rs
index 5ced7c0a..a36a8b2b 100644
--- a/rsvg_internals/src/filters/node.rs
+++ b/rsvg_internals/src/filters/node.rs
@@ -1,6 +1,6 @@
 //! The <filter> node.
 use cairo;
-use markup5ever::local_name;
+use markup5ever::{expanded_name, local_name, namespace_url, ns};
 
 use crate::bbox::BoundingBox;
 use crate::coord_units::CoordUnits;
@@ -117,8 +117,8 @@ impl NodeTrait for NodeFilter {
     fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
         // Parse filterUnits first as it affects x, y, width, height checks.
         for (attr, value) in pbag.iter() {
-            match attr {
-                local_name!("filterUnits") => self.filterunits = attr.parse(value)?,
+            match attr.expanded() {
+                expanded_name!(svg "filterUnits") => self.filterunits = attr.parse(value)?,
                 _ => (),
             }
         }
@@ -162,22 +162,22 @@ impl NodeTrait for NodeFilter {
 
         // Parse the rest of the attributes.
         for (attr, value) in pbag.iter() {
-            match attr {
-                local_name!("x") => {
+            match attr.expanded() {
+                expanded_name!(svg "x") => {
                     self.x = attr.parse_and_validate(value, check_units_horizontal)?
                 }
-                local_name!("y") => {
+                expanded_name!(svg "y") => {
                     self.y = attr.parse_and_validate(value, check_units_vertical)?
                 }
-                local_name!("width") => {
+                expanded_name!(svg "width") => {
                     self.width = attr
                         .parse_and_validate(value, check_units_horizontal_and_ensure_nonnegative)?
                 }
-                local_name!("height") => {
+                expanded_name!(svg "height") => {
                     self.height =
                         attr.parse_and_validate(value, check_units_vertical_and_ensure_nonnegative)?
                 }
-                local_name!("primitiveUnits") => self.primitiveunits = attr.parse(value)?,
+                expanded_name!(svg "primitiveUnits") => self.primitiveunits = attr.parse(value)?,
                 _ => (),
             }
         }
diff --git a/rsvg_internals/src/filters/offset.rs b/rsvg_internals/src/filters/offset.rs
index 765076e9..eeb96c4d 100644
--- a/rsvg_internals/src/filters/offset.rs
+++ b/rsvg_internals/src/filters/offset.rs
@@ -1,5 +1,5 @@
 use cairo::{self, ImageSurface};
-use markup5ever::local_name;
+use markup5ever::{expanded_name, local_name, namespace_url, ns};
 
 use crate::drawing_ctx::DrawingCtx;
 use crate::error::AttributeResultExt;
@@ -39,9 +39,9 @@ impl NodeTrait for Offset {
         self.base.set_atts(parent, pbag)?;
 
         for (attr, value) in pbag.iter() {
-            match attr {
-                local_name!("dx") => self.dx = parsers::number(value).attribute(attr)?,
-                local_name!("dy") => self.dy = parsers::number(value).attribute(attr)?,
+            match attr.expanded() {
+                expanded_name!(svg "dx") => self.dx = parsers::number(value).attribute(attr)?,
+                expanded_name!(svg "dy") => self.dy = parsers::number(value).attribute(attr)?,
                 _ => (),
             }
         }
diff --git a/rsvg_internals/src/filters/turbulence.rs b/rsvg_internals/src/filters/turbulence.rs
index 8e5743ad..fe4da196 100644
--- a/rsvg_internals/src/filters/turbulence.rs
+++ b/rsvg_internals/src/filters/turbulence.rs
@@ -1,5 +1,5 @@
 use cairo::{self, ImageSurface};
-use markup5ever::{local_name, LocalName};
+use markup5ever::{expanded_name, local_name, namespace_url, ns, QualName};
 
 use crate::drawing_ctx::DrawingCtx;
 use crate::error::{AttributeResultExt, NodeError};
@@ -64,8 +64,8 @@ impl NodeTrait for Turbulence {
         self.base.set_atts(parent, pbag)?;
 
         for (attr, value) in pbag.iter() {
-            match attr {
-                local_name!("baseFrequency") => {
+            match attr.expanded() {
+                expanded_name!(svg "baseFrequency") => {
                     self.base_frequency = parsers::number_optional_number(value)
                         .attribute(attr.clone())
                         .and_then(|(x, y)| {
@@ -76,11 +76,11 @@ impl NodeTrait for Turbulence {
                             }
                         })?
                 }
-                local_name!("numOctaves") => {
+                expanded_name!(svg "numOctaves") => {
                     self.num_octaves = parsers::integer(value).attribute(attr)?
                 }
                 // Yes, seed needs to be parsed as a number and then truncated.
-                local_name!("seed") => {
+                expanded_name!(svg "seed") => {
                     self.seed = parsers::number(value)
                         .map(|x| {
                             clamp(
@@ -91,8 +91,8 @@ impl NodeTrait for Turbulence {
                         })
                         .attribute(attr)?
                 }
-                local_name!("stitchTiles") => self.stitch_tiles = StitchTiles::parse(attr, value)?,
-                local_name!("type") => self.type_ = NoiseType::parse(attr, value)?,
+                expanded_name!(svg "stitchTiles") => self.stitch_tiles = StitchTiles::parse(attr, value)?,
+                expanded_name!(svg "type") => self.type_ = NoiseType::parse(attr, value)?,
                 _ => (),
             }
         }
@@ -427,7 +427,7 @@ impl Filter for Turbulence {
 }
 
 impl StitchTiles {
-    fn parse(attr: LocalName, s: &str) -> Result<Self, NodeError> {
+    fn parse(attr: QualName, s: &str) -> Result<Self, NodeError> {
         match s {
             "stitch" => Ok(StitchTiles::Stitch),
             "noStitch" => Ok(StitchTiles::NoStitch),
@@ -440,7 +440,7 @@ impl StitchTiles {
 }
 
 impl NoiseType {
-    fn parse(attr: LocalName, s: &str) -> Result<Self, NodeError> {
+    fn parse(attr: QualName, s: &str) -> Result<Self, NodeError> {
         match s {
             "fractalNoise" => Ok(NoiseType::FractalNoise),
             "turbulence" => Ok(NoiseType::Turbulence),
diff --git a/rsvg_internals/src/gradient.rs b/rsvg_internals/src/gradient.rs
index 2e639eac..174e1bae 100644
--- a/rsvg_internals/src/gradient.rs
+++ b/rsvg_internals/src/gradient.rs
@@ -1,6 +1,6 @@
 use cairo;
 use cssparser::{self, CowRcStr, Parser, Token};
-use markup5ever::local_name;
+use markup5ever::{expanded_name, local_name, namespace_url, ns};
 use std::cell::RefCell;
 
 use crate::allowed_url::Fragment;
@@ -143,8 +143,8 @@ fn validate_offset(length: LengthBoth) -> Result<LengthBoth, ValueErrorKind> {
 impl NodeTrait for NodeStop {
     fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
         for (attr, value) in pbag.iter() {
-            match attr {
-                local_name!("offset") => {
+            match attr.expanded() {
+                expanded_name!(svg "offset") => {
                     self.offset = attr
                         .parse_and_validate(value, validate_offset)
                         .map(|l| UnitInterval::clamp(l.length()))?
@@ -559,11 +559,11 @@ impl_get_unresolved!(NodeRadialGradient);
 impl Common {
     fn set_atts(&mut self, pbag: &PropertyBag<'_>) -> NodeResult {
         for (attr, value) in pbag.iter() {
-            match attr {
-                local_name!("gradientUnits") => self.units = Some(attr.parse(value)?),
-                local_name!("gradientTransform") => self.affine = Some(attr.parse(value)?),
-                local_name!("spreadMethod") => self.spread = Some(attr.parse(value)?),
-                local_name!("xlink:href") => {
+            match attr.expanded() {
+                expanded_name!(svg "gradientUnits") => self.units = Some(attr.parse(value)?),
+                expanded_name!(svg "gradientTransform") => self.affine = Some(attr.parse(value)?),
+                expanded_name!(svg "spreadMethod") => self.spread = Some(attr.parse(value)?),
+                expanded_name!(xlink "href") => {
                     self.fallback = Some(Fragment::parse(value).attribute(attr)?)
                 }
                 _ => (),
@@ -579,11 +579,11 @@ impl NodeTrait for NodeLinearGradient {
         self.common.set_atts(pbag)?;
 
         for (attr, value) in pbag.iter() {
-            match attr {
-                local_name!("x1") => self.x1 = Some(attr.parse(value)?),
-                local_name!("y1") => self.y1 = Some(attr.parse(value)?),
-                local_name!("x2") => self.x2 = Some(attr.parse(value)?),
-                local_name!("y2") => self.y2 = Some(attr.parse(value)?),
+            match attr.expanded() {
+                expanded_name!(svg "x1") => self.x1 = Some(attr.parse(value)?),
+                expanded_name!(svg "y1") => self.y1 = Some(attr.parse(value)?),
+                expanded_name!(svg "x2") => self.x2 = Some(attr.parse(value)?),
+                expanded_name!(svg "y2") => self.y2 = Some(attr.parse(value)?),
 
                 _ => (),
             }
@@ -598,12 +598,12 @@ impl NodeTrait for NodeRadialGradient {
         self.common.set_atts(pbag)?;
 
         for (attr, value) in pbag.iter() {
-            match attr {
-                local_name!("cx") => self.cx = Some(attr.parse(value)?),
-                local_name!("cy") => self.cy = Some(attr.parse(value)?),
-                local_name!("r") => self.r = Some(attr.parse(value)?),
-                local_name!("fx") => self.fx = Some(attr.parse(value)?),
-                local_name!("fy") => self.fy = Some(attr.parse(value)?),
+            match attr.expanded() {
+                expanded_name!(svg "cx") => self.cx = Some(attr.parse(value)?),
+                expanded_name!(svg "cy") => self.cy = Some(attr.parse(value)?),
+                expanded_name!(svg "r") => self.r = Some(attr.parse(value)?),
+                expanded_name!(svg "fx") => self.fx = Some(attr.parse(value)?),
+                expanded_name!(svg "fy") => self.fy = Some(attr.parse(value)?),
 
                 _ => (),
             }
@@ -823,7 +823,7 @@ mod tests {
     fn gradient_resolved_from_defaults_is_really_resolved() {
         let node = RsvgNode::new(NodeData::new(
             NodeType::LinearGradient,
-            QualName::new(None, ns!(svg), local_name!("linearGradient")),
+            &QualName::new(None, ns!(svg), local_name!("linearGradient")),
             None,
             None,
             Box::new(NodeLinearGradient::default())
@@ -837,7 +837,7 @@ mod tests {
 
         let node = RsvgNode::new(NodeData::new(
             NodeType::RadialGradient,
-            QualName::new(None, ns!(svg), local_name!("radialGradient")),
+            &QualName::new(None, ns!(svg), local_name!("radialGradient")),
             None,
             None,
             Box::new(NodeRadialGradient::default())
diff --git a/rsvg_internals/src/image.rs b/rsvg_internals/src/image.rs
index f054d5a2..105c2f31 100644
--- a/rsvg_internals/src/image.rs
+++ b/rsvg_internals/src/image.rs
@@ -1,6 +1,6 @@
 use cairo;
 use cairo::Rectangle;
-use markup5ever::local_name;
+use markup5ever::{expanded_name, local_name, namespace_url, ns};
 
 use crate::allowed_url::Href;
 use crate::aspect_ratio::AspectRatio;
@@ -28,19 +28,19 @@ pub struct NodeImage {
 impl NodeTrait for NodeImage {
     fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
         for (attr, value) in pbag.iter() {
-            match attr {
-                local_name!("x") => self.x = attr.parse(value)?,
-                local_name!("y") => self.y = attr.parse(value)?,
-                local_name!("width") => {
+            match attr.expanded() {
+                expanded_name!(svg "x") => self.x = attr.parse(value)?,
+                expanded_name!(svg "y") => self.y = attr.parse(value)?,
+                expanded_name!(svg "width") => {
                     self.w = attr.parse_and_validate(value, LengthHorizontal::check_nonnegative)?
                 }
-                local_name!("height") => {
+                expanded_name!(svg "height") => {
                     self.h = attr.parse_and_validate(value, LengthVertical::check_nonnegative)?
                 }
-                local_name!("preserveAspectRatio") => self.aspect = attr.parse(value)?,
+                expanded_name!(svg "preserveAspectRatio") => self.aspect = attr.parse(value)?,
 
                 // "path" is used by some older Adobe Illustrator versions
-                local_name!("xlink:href") | local_name!("path") => {
+                expanded_name!(xlink "href") | expanded_name!(svg "path") => {
                     let href = Href::parse(value).map_err(|_| {
                         NodeError::parse_error(attr, ParseError::new("could not parse href"))
                     })?;
diff --git a/rsvg_internals/src/link.rs b/rsvg_internals/src/link.rs
index 7c5ab3d9..a98190c2 100644
--- a/rsvg_internals/src/link.rs
+++ b/rsvg_internals/src/link.rs
@@ -1,5 +1,5 @@
 use lazy_static::lazy_static;
-use markup5ever::local_name;
+use markup5ever::{expanded_name, local_name, namespace_url, ns};
 use regex::{Captures, Regex};
 use std::borrow::Cow;
 
@@ -17,8 +17,8 @@ pub struct NodeLink {
 impl NodeTrait for NodeLink {
     fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
         for (attr, value) in pbag.iter() {
-            match attr {
-                local_name!("xlink:href") => self.link = Some(value.to_owned()),
+            match attr.expanded() {
+                expanded_name!(xlink "href") => self.link = Some(value.to_owned()),
                 _ => (),
             }
         }
diff --git a/rsvg_internals/src/marker.rs b/rsvg_internals/src/marker.rs
index 21c22894..a507ba01 100644
--- a/rsvg_internals/src/marker.rs
+++ b/rsvg_internals/src/marker.rs
@@ -3,7 +3,7 @@ use std::ops::Deref;
 
 use cairo::Rectangle;
 use cssparser::{CowRcStr, Parser, Token};
-use markup5ever::local_name;
+use markup5ever::{expanded_name, local_name, namespace_url, ns};
 
 use crate::allowed_url::Fragment;
 use crate::angle::Angle;
@@ -196,21 +196,21 @@ impl NodeMarker {
 impl NodeTrait for NodeMarker {
     fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
         for (attr, value) in pbag.iter() {
-            match attr {
-                local_name!("markerUnits") => self.units = attr.parse(value)?,
-                local_name!("refX") => self.ref_x = attr.parse(value)?,
-                local_name!("refY") => self.ref_y = attr.parse(value)?,
-                local_name!("markerWidth") => {
+            match attr.expanded() {
+                expanded_name!(svg "markerUnits") => self.units = attr.parse(value)?,
+                expanded_name!(svg "refX") => self.ref_x = attr.parse(value)?,
+                expanded_name!(svg "refY") => self.ref_y = attr.parse(value)?,
+                expanded_name!(svg "markerWidth") => {
                     self.width =
                         attr.parse_and_validate(value, LengthHorizontal::check_nonnegative)?
                 }
-                local_name!("markerHeight") => {
+                expanded_name!(svg "markerHeight") => {
                     self.height =
                         attr.parse_and_validate(value, LengthVertical::check_nonnegative)?
                 }
-                local_name!("orient") => self.orient = attr.parse(value)?,
-                local_name!("preserveAspectRatio") => self.aspect = attr.parse(value)?,
-                local_name!("viewBox") => self.vbox = Some(attr.parse(value)?),
+                expanded_name!(svg "orient") => self.orient = attr.parse(value)?,
+                expanded_name!(svg "preserveAspectRatio") => self.aspect = attr.parse(value)?,
+                expanded_name!(svg "viewBox") => self.vbox = Some(attr.parse(value)?),
                 _ => (),
             }
         }
diff --git a/rsvg_internals/src/mask.rs b/rsvg_internals/src/mask.rs
index 8226d60b..6ea014d8 100644
--- a/rsvg_internals/src/mask.rs
+++ b/rsvg_internals/src/mask.rs
@@ -1,5 +1,5 @@
 use cairo;
-use markup5ever::local_name;
+use markup5ever::{expanded_name, local_name, namespace_url, ns};
 
 use crate::bbox::BoundingBox;
 use crate::coord_units::CoordUnits;
@@ -188,19 +188,19 @@ fn compute_luminance_to_alpha(
 impl NodeTrait for NodeMask {
     fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
         for (attr, value) in pbag.iter() {
-            match attr {
-                local_name!("x") => self.x = attr.parse(value)?,
-                local_name!("y") => self.y = attr.parse(value)?,
-                local_name!("width") => {
+            match attr.expanded() {
+                expanded_name!(svg "x") => self.x = attr.parse(value)?,
+                expanded_name!(svg "y") => self.y = attr.parse(value)?,
+                expanded_name!(svg "width") => {
                     self.width =
                         attr.parse_and_validate(value, LengthHorizontal::check_nonnegative)?
                 }
-                local_name!("height") => {
+                expanded_name!(svg "height") => {
                     self.height =
                         attr.parse_and_validate(value, LengthVertical::check_nonnegative)?
                 }
-                local_name!("maskUnits") => self.units = attr.parse(value)?,
-                local_name!("maskContentUnits") => self.content_units = attr.parse(value)?,
+                expanded_name!(svg "maskUnits") => self.units = attr.parse(value)?,
+                expanded_name!(svg "maskContentUnits") => self.content_units = attr.parse(value)?,
                 _ => (),
             }
         }
diff --git a/rsvg_internals/src/node.rs b/rsvg_internals/src/node.rs
index 5d494d12..e4aae4a5 100644
--- a/rsvg_internals/src/node.rs
+++ b/rsvg_internals/src/node.rs
@@ -1,6 +1,6 @@
 use cairo::Matrix;
 use downcast_rs::*;
-use markup5ever::{local_name, LocalName, QualName};
+use markup5ever::{expanded_name, local_name, namespace_url, ns, QualName};
 use std::cell::Ref;
 use std::collections::HashSet;
 use std::fmt;
@@ -29,7 +29,7 @@ pub struct NodeData {
     id: Option<String>,    // id attribute from XML element
     class: Option<String>, // class attribute from XML element
     specified_values: SpecifiedValues,
-    important_styles: HashSet<LocalName>,
+    important_styles: HashSet<QualName>,
     result: NodeResult,
     transform: Matrix,
     values: ComputedValues,
@@ -41,14 +41,14 @@ pub struct NodeData {
 impl NodeData {
     pub fn new(
         node_type: NodeType,
-        element_name: QualName,
+        element_name: &QualName,
         id: Option<&str>,
         class: Option<&str>,
         node_impl: Box<dyn NodeTrait>,
     ) -> NodeData {
         NodeData {
             node_type,
-            element_name,
+            element_name: element_name.clone(),
             id: id.map(str::to_string),
             class: class.map(str::to_string),
             specified_values: Default::default(),
@@ -124,8 +124,8 @@ impl NodeData {
 
     fn save_style_attribute(&mut self, pbag: &PropertyBag<'_>) {
         for (attr, value) in pbag.iter() {
-            match attr {
-                local_name!("style") => self.style_attr.push_str(value),
+            match attr.expanded() {
+                expanded_name!(svg "style") => self.style_attr.push_str(value),
                 _ => (),
             }
         }
@@ -133,8 +133,8 @@ impl NodeData {
 
     fn set_transform_attribute(&mut self, pbag: &PropertyBag<'_>) -> Result<(), NodeError> {
         for (attr, value) in pbag.iter() {
-            match attr {
-                local_name!("transform") => {
+            match attr.expanded() {
+                expanded_name!(svg "transform") => {
                     return Matrix::parse_str(value).attribute(attr).and_then(|affine| {
                         self.transform = affine;
                         Ok(())
@@ -157,18 +157,18 @@ impl NodeData {
         for (attr, value) in pbag.iter() {
             // FIXME: move this to "try {}" when we can bump the rustc version dependency
             let mut parse = || {
-                match attr {
-                    local_name!("requiredExtensions") if cond => {
+                match attr.expanded() {
+                    expanded_name!(svg "requiredExtensions") if cond => {
                         cond = RequiredExtensions::from_attribute(value)
                             .map(|RequiredExtensions(res)| res)?;
                     }
 
-                    local_name!("requiredFeatures") if cond => {
+                    expanded_name!(svg "requiredFeatures") if cond => {
                         cond = RequiredFeatures::from_attribute(value)
                             .map(|RequiredFeatures(res)| res)?;
                     }
 
-                    local_name!("systemLanguage") if cond => {
+                    expanded_name!(svg "systemLanguage") if cond => {
                         cond = SystemLanguage::from_attribute(value, locale)
                             .map(|SystemLanguage(res)| res)?;
                     }
diff --git a/rsvg_internals/src/parsers.rs b/rsvg_internals/src/parsers.rs
index f27d8c49..2d305930 100644
--- a/rsvg_internals/src/parsers.rs
+++ b/rsvg_internals/src/parsers.rs
@@ -1,5 +1,5 @@
 use cssparser::{BasicParseError, Parser, ParserInput, Token};
-use markup5ever::LocalName;
+use markup5ever::QualName;
 
 use std::str;
 
@@ -77,7 +77,7 @@ pub trait ParseValue<T: Parse<Err = ValueErrorKind>> {
     ) -> Result<T, NodeError>;
 }
 
-impl<T: Parse<Err = ValueErrorKind>> ParseValue<T> for LocalName {
+impl<T: Parse<Err = ValueErrorKind>> ParseValue<T> for QualName {
     fn parse(&self, value: &str) -> Result<T, NodeError> {
         let mut input = ParserInput::new(value);
         let mut parser = Parser::new(&mut input);
diff --git a/rsvg_internals/src/pattern.rs b/rsvg_internals/src/pattern.rs
index 4d9afe90..41df52ba 100644
--- a/rsvg_internals/src/pattern.rs
+++ b/rsvg_internals/src/pattern.rs
@@ -1,5 +1,5 @@
 use cairo;
-use markup5ever::local_name;
+use markup5ever::{expanded_name, local_name, namespace_url, ns};
 use std::cell::RefCell;
 use std::f64;
 
@@ -118,26 +118,26 @@ pub struct NodePattern {
 impl NodeTrait for NodePattern {
     fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
         for (attr, value) in pbag.iter() {
-            match attr {
-                local_name!("patternUnits") => self.common.units = Some(attr.parse(value)?),
-                local_name!("patternContentUnits") => {
+            match attr.expanded() {
+                expanded_name!(svg "patternUnits") => self.common.units = Some(attr.parse(value)?),
+                expanded_name!(svg "patternContentUnits") => {
                     self.common.content_units = Some(attr.parse(value)?)
                 }
-                local_name!("viewBox") => self.common.vbox = Some(Some(attr.parse(value)?)),
-                local_name!("preserveAspectRatio") => {
+                expanded_name!(svg "viewBox") => self.common.vbox = Some(Some(attr.parse(value)?)),
+                expanded_name!(svg "preserveAspectRatio") => {
                     self.common.preserve_aspect_ratio = Some(attr.parse(value)?)
                 }
-                local_name!("patternTransform") => self.common.affine = Some(attr.parse(value)?),
-                local_name!("xlink:href") => {
+                expanded_name!(svg "patternTransform") => self.common.affine = Some(attr.parse(value)?),
+                expanded_name!(xlink "href") => {
                     self.fallback = Some(Fragment::parse(value).attribute(attr)?);
                 }
-                local_name!("x") => self.common.x = Some(attr.parse(value)?),
-                local_name!("y") => self.common.y = Some(attr.parse(value)?),
-                local_name!("width") => {
+                expanded_name!(svg "x") => self.common.x = Some(attr.parse(value)?),
+                expanded_name!(svg "y") => self.common.y = Some(attr.parse(value)?),
+                expanded_name!(svg "width") => {
                     self.common.width =
                         Some(attr.parse_and_validate(value, LengthHorizontal::check_nonnegative)?)
                 }
-                local_name!("height") => {
+                expanded_name!(svg "height") => {
                     self.common.height =
                         Some(attr.parse_and_validate(value, LengthVertical::check_nonnegative)?)
                 }
@@ -595,7 +595,7 @@ mod tests {
     fn pattern_resolved_from_defaults_is_really_resolved() {
         let node = RsvgNode::new(NodeData::new(
             NodeType::Pattern,
-            QualName::new(None, ns!(svg), local_name!("pattern")),
+            &QualName::new(None, ns!(svg), local_name!("pattern")),
             None,
             None,
             Box::new(NodePattern::default()),
diff --git a/rsvg_internals/src/properties.rs b/rsvg_internals/src/properties.rs
index e846ff96..778071a2 100644
--- a/rsvg_internals/src/properties.rs
+++ b/rsvg_internals/src/properties.rs
@@ -1,5 +1,5 @@
 use cssparser::{self, DeclarationListParser, Parser, ParserInput};
-use markup5ever::{local_name, LocalName};
+use markup5ever::{expanded_name, local_name, namespace_url, ns, QualName};
 use std::collections::HashSet;
 
 use crate::css::{DeclParser, Declaration};
@@ -223,76 +223,76 @@ pub struct ComputedValues {
 }
 
 #[cfg_attr(rustfmt, rustfmt_skip)]
-pub fn parse_attribute_value_into_parsed_property(attr: &LocalName, input: &mut Parser, accept_shorthands: 
bool) -> Result<ParsedProperty, ValueErrorKind> {
+pub fn parse_attribute_value_into_parsed_property(attr: &QualName, input: &mut Parser, accept_shorthands: 
bool) -> Result<ParsedProperty, ValueErrorKind> {
     // please keep these sorted
-    match attr {
-        local_name!("baseline-shift") =>
+    match attr.expanded() {
+        expanded_name!(svg "baseline-shift") =>
             Ok(ParsedProperty::BaselineShift(parse_input(input)?)),
 
-        local_name!("clip-path") =>
+        expanded_name!(svg "clip-path") =>
             Ok(ParsedProperty::ClipPath(parse_input(input)?)),
 
-        local_name!("clip-rule") =>
+        expanded_name!(svg "clip-rule") =>
             Ok(ParsedProperty::ClipRule(parse_input(input)?)),
 
-        local_name!("color") =>
+        expanded_name!(svg "color") =>
             Ok(ParsedProperty::Color(parse_input(input)?)),
 
-        local_name!("color-interpolation-filters") =>
+        expanded_name!(svg "color-interpolation-filters") =>
             Ok(ParsedProperty::ColorInterpolationFilters(parse_input(input)?)),
 
-        local_name!("direction") =>
+        expanded_name!(svg "direction") =>
             Ok(ParsedProperty::Direction(parse_input(input)?)),
 
-        local_name!("display") =>
+        expanded_name!(svg "display") =>
             Ok(ParsedProperty::Display(parse_input(input)?)),
 
-        local_name!("enable-background") =>
+        expanded_name!(svg "enable-background") =>
             Ok(ParsedProperty::EnableBackground(parse_input(input)?)),
 
-        local_name!("fill") =>
+        expanded_name!(svg "fill") =>
             Ok(ParsedProperty::Fill(parse_input(input)?)),
 
-        local_name!("fill-opacity") =>
+        expanded_name!(svg "fill-opacity") =>
             Ok(ParsedProperty::FillOpacity(parse_input(input)?)),
 
-        local_name!("fill-rule") =>
+        expanded_name!(svg "fill-rule") =>
             Ok(ParsedProperty::FillRule(parse_input(input)?)),
 
-        local_name!("filter") =>
+        expanded_name!(svg "filter") =>
             Ok(ParsedProperty::Filter(parse_input(input)?)),
 
-        local_name!("flood-color") =>
+        expanded_name!(svg "flood-color") =>
             Ok(ParsedProperty::FloodColor(parse_input(input)?)),
 
-        local_name!("flood-opacity") =>
+        expanded_name!(svg "flood-opacity") =>
             Ok(ParsedProperty::FloodOpacity(parse_input(input)?)),
 
-        local_name!("font-family") =>
+        expanded_name!(svg "font-family") =>
             Ok(ParsedProperty::FontFamily(parse_input(input)?)),
 
-        local_name!("font-size") =>
+        expanded_name!(svg "font-size") =>
             Ok(ParsedProperty::FontSize(parse_input(input)?)),
 
-        local_name!("font-stretch") =>
+        expanded_name!(svg "font-stretch") =>
             Ok(ParsedProperty::FontStretch(parse_input(input)?)),
 
-        local_name!("font-style") =>
+        expanded_name!(svg "font-style") =>
             Ok(ParsedProperty::FontStyle(parse_input(input)?)),
 
-        local_name!("font-variant") =>
+        expanded_name!(svg "font-variant") =>
             Ok(ParsedProperty::FontVariant(parse_input(input)?)),
 
-        local_name!("font-weight") =>
+        expanded_name!(svg "font-weight") =>
             Ok(ParsedProperty::FontWeight(parse_input(input)?)),
 
-        local_name!("letter-spacing") =>
+        expanded_name!(svg "letter-spacing") =>
             Ok(ParsedProperty::LetterSpacing(parse_input(input)?)),
 
-        local_name!("lighting-color") =>
+        expanded_name!(svg "lighting-color") =>
             Ok(ParsedProperty::LightingColor(parse_input(input)?)),
 
-        local_name!("marker") => {
+        expanded_name!(svg "marker") => {
             if accept_shorthands {
                 Ok(ParsedProperty::Marker(parse_input(input)?))
             } else {
@@ -300,73 +300,73 @@ pub fn parse_attribute_value_into_parsed_property(attr: &LocalName, input: &mut
             }
         }
 
-        local_name!("marker-end") =>
+        expanded_name!(svg "marker-end") =>
             Ok(ParsedProperty::MarkerEnd(parse_input(input)?)),
 
-        local_name!("marker-mid") =>
+        expanded_name!(svg "marker-mid") =>
             Ok(ParsedProperty::MarkerMid(parse_input(input)?)),
 
-        local_name!("marker-start") =>
+        expanded_name!(svg "marker-start") =>
             Ok(ParsedProperty::MarkerStart(parse_input(input)?)),
 
-        local_name!("mask") =>
+        expanded_name!(svg "mask") =>
             Ok(ParsedProperty::Mask(parse_input(input)?)),
 
-        local_name!("opacity") =>
+        expanded_name!(svg "opacity") =>
             Ok(ParsedProperty::Opacity(parse_input(input)?)),
 
-        local_name!("overflow") =>
+        expanded_name!(svg "overflow") =>
             Ok(ParsedProperty::Overflow(parse_input(input)?)),
 
-        local_name!("shape-rendering") =>
+        expanded_name!(svg "shape-rendering") =>
             Ok(ParsedProperty::ShapeRendering(parse_input(input)?)),
 
-        local_name!("stop-color") =>
+        expanded_name!(svg "stop-color") =>
             Ok(ParsedProperty::StopColor(parse_input(input)?)),
 
-        local_name!("stop-opacity") =>
+        expanded_name!(svg "stop-opacity") =>
             Ok(ParsedProperty::StopOpacity(parse_input(input)?)),
 
-        local_name!("stroke") =>
+        expanded_name!(svg "stroke") =>
             Ok(ParsedProperty::Stroke(parse_input(input)?)),
 
-        local_name!("stroke-dasharray") =>
+        expanded_name!(svg "stroke-dasharray") =>
             Ok(ParsedProperty::StrokeDasharray(parse_input(input)?)),
 
-        local_name!("stroke-dashoffset") =>
+        expanded_name!(svg "stroke-dashoffset") =>
             Ok(ParsedProperty::StrokeDashoffset(parse_input(input)?)),
 
-        local_name!("stroke-linecap") =>
+        expanded_name!(svg "stroke-linecap") =>
             Ok(ParsedProperty::StrokeLinecap(parse_input(input)?)),
 
-        local_name!("stroke-linejoin") =>
+        expanded_name!(svg "stroke-linejoin") =>
             Ok(ParsedProperty::StrokeLinejoin(parse_input(input)?)),
 
-        local_name!("stroke-miterlimit") =>
+        expanded_name!(svg "stroke-miterlimit") =>
             Ok(ParsedProperty::StrokeMiterlimit(parse_input(input)?)),
 
-        local_name!("stroke-opacity") =>
+        expanded_name!(svg "stroke-opacity") =>
             Ok(ParsedProperty::StrokeOpacity(parse_input(input)?)),
 
-        local_name!("stroke-width") =>
+        expanded_name!(svg "stroke-width") =>
             Ok(ParsedProperty::StrokeWidth(parse_input(input)?)),
 
-        local_name!("text-anchor") =>
+        expanded_name!(svg "text-anchor") =>
             Ok(ParsedProperty::TextAnchor(parse_input(input)?)),
 
-        local_name!("text-decoration") =>
+        expanded_name!(svg "text-decoration") =>
             Ok(ParsedProperty::TextDecoration(parse_input(input)?)),
 
-        local_name!("text-rendering") =>
+        expanded_name!(svg "text-rendering") =>
             Ok(ParsedProperty::TextRendering(parse_input(input)?)),
 
-        local_name!("unicode-bidi") =>
+        expanded_name!(svg "unicode-bidi") =>
             Ok(ParsedProperty::UnicodeBidi(parse_input(input)?)),
 
-        local_name!("visibility") =>
+        expanded_name!(svg "visibility") =>
             Ok(ParsedProperty::Visibility(parse_input(input)?)),
 
-        local_name!("writing-mode") =>
+        expanded_name!(svg "writing-mode") =>
             Ok(ParsedProperty::WritingMode(parse_input(input)?)),
 
         _ => Err(ValueErrorKind::UnknownProperty)
@@ -520,7 +520,7 @@ impl SpecifiedValues {
 
     fn parse_attribute_pair(
         &mut self,
-        attr: LocalName,
+        attr: QualName,
         value: &str,
         accept_shorthands: bool,
     ) -> Result<(), NodeError> {
@@ -556,8 +556,8 @@ impl SpecifiedValues {
         pbag: &PropertyBag<'_>,
     ) -> Result<(), NodeError> {
         for (attr, value) in pbag.iter() {
-            match attr {
-                local_name!("xml:lang") => {
+            match attr.expanded() {
+                expanded_name!(svg "xml:lang") => {
                     // xml:lang is a non-presentation attribute and as such cannot have the
                     // "inherit" value.  So, we don't call parse_attribute_pair() for it, but
                     // rather call its parser directly.
@@ -565,7 +565,7 @@ impl SpecifiedValues {
                         SpecifiedValue::Specified(XmlLang::parse_str(value).attribute(attr)?);
                 }
 
-                local_name!("xml:space") => {
+                expanded_name!(svg "xml:space") => {
                     // xml:space is a non-presentation attribute and as such cannot have the
                     // "inherit" value.  So, we don't call parse_attribute_pair() for it, but
                     // rather call its parser directly.
@@ -583,7 +583,7 @@ impl SpecifiedValues {
     pub fn set_property_from_declaration(
         &mut self,
         declaration: &Declaration,
-        important_styles: &mut HashSet<LocalName>,
+        important_styles: &mut HashSet<QualName>,
     ) {
         if !declaration.important && important_styles.contains(&declaration.attribute) {
             return;
@@ -599,7 +599,7 @@ impl SpecifiedValues {
     pub fn parse_style_declarations(
         &mut self,
         declarations: &str,
-        important_styles: &mut HashSet<LocalName>,
+        important_styles: &mut HashSet<QualName>,
     ) -> Result<(), NodeError> {
         let mut input = ParserInput::new(declarations);
         let mut parser = Parser::new(&mut input);
diff --git a/rsvg_internals/src/property_bag.rs b/rsvg_internals/src/property_bag.rs
index 4cb979dc..9261783f 100644
--- a/rsvg_internals/src/property_bag.rs
+++ b/rsvg_internals/src/property_bag.rs
@@ -1,81 +1,18 @@
 use libc;
 
-use std::ffi::CStr;
 use std::mem;
 use std::slice;
 use std::str;
 
-use markup5ever::LocalName;
+use markup5ever::QualName;
 
-enum Attribute<'a> {
-    CStr(&'a CStr),
-    Unterminated(&'a str),
-}
-
-pub struct PropertyBag<'a>(Vec<(LocalName, Attribute<'a>)>);
+use crate::util::{make_qual_name, opt_utf8_cstr, utf8_cstr};
 
-pub struct PropertyBagIter<'a>(slice::Iter<'a, (LocalName, Attribute<'a>)>);
-
-trait Utf8CStrToStr {
-    fn to_str_utf8(&self) -> &str;
-}
+pub struct PropertyBag<'a>(Vec<(QualName, &'a str)>);
 
-impl Utf8CStrToStr for CStr {
-    fn to_str_utf8(&self) -> &str {
-        // We can *only* do this when the CStr comes from a C string that was validated
-        // as UTF-8 on the C side of things.  In our case, the C strings from libxml2 and
-        // are valid UTF-8.
-        unsafe { str::from_utf8_unchecked(self.to_bytes()) }
-    }
-}
+pub struct PropertyBagIter<'a>(slice::Iter<'a, (QualName, &'a str)>);
 
 impl<'a> PropertyBag<'a> {
-    /// Creates an iterable `PropertyBag` from a C array of borrowed C strings.
-    ///
-    /// With libxml2's SAX parser, the caller's callback for "element start"
-    /// gets passed a `xmlChar **` of attribute/value pairs.  Even indices
-    /// in the array are pointers to attribute names; odd indices are
-    /// pointers to attribute values.  The array terminates with a NULL
-    /// element in an even index.
-    ///
-    /// This function is unsafe because the caller must guarantee the following:
-    ///
-    /// * `pairs` is a valid pointer, or NULL for an empty array
-    ///
-    /// * `pairs` has key/value pairs and is NULL terminated
-    ///
-    /// * Both keys and values are valid UTF-8, nul-terminated C strings
-    ///
-    /// The lifetime of the `PropertyBag` should be considered the same as the lifetime of the
-    /// `pairs` array, as the property bag does not copy the strings - it directly stores pointers
-    /// into that array's strings.
-    pub unsafe fn new_from_key_value_pairs(pairs: *const *const libc::c_char) -> PropertyBag<'a> {
-        let mut array = Vec::new();
-
-        if !pairs.is_null() {
-            let mut i = 0;
-            loop {
-                let key = *pairs.offset(i);
-                if !key.is_null() {
-                    let val = *pairs.offset(i + 1);
-                    assert!(!val.is_null());
-
-                    let key_str = CStr::from_ptr(key);
-                    let val_str = CStr::from_ptr(val);
-
-                    let attr = LocalName::from(key_str.to_str_utf8());
-                    array.push((attr, Attribute::CStr(val_str)));
-                } else {
-                    break;
-                }
-
-                i += 2;
-            }
-        }
-
-        PropertyBag(array)
-    }
-
     /// Creates an iterable `PropertyBag` from a C array of borrowed C strings.
     ///
     /// With libxml2's SAX parser, the caller's startElementNsSAX2Func
@@ -106,13 +43,18 @@ impl<'a> PropertyBag<'a> {
             let mut i = 0;
             while i < n_attributes * 5 {
                 let localname = attrs[i];
-                let _prefix = attrs[i + 1];
-                let _uri = attrs[i + 2];
+                let prefix = attrs[i + 1];
+                let uri = attrs[i + 2];
                 let value_start = attrs[i + 3];
                 let value_end = attrs[i + 4];
 
                 assert!(!localname.is_null());
 
+                let prefix = opt_utf8_cstr(prefix);
+                let uri = opt_utf8_cstr(uri);
+                let localname = utf8_cstr(localname);
+                let qual_name = make_qual_name(prefix, uri, localname);
+
                 if !value_start.is_null() && !value_end.is_null() {
                     assert!(value_end >= value_start);
 
@@ -125,9 +67,7 @@ impl<'a> PropertyBag<'a> {
                     let value_slice = slice::from_raw_parts(value_start as *const u8, len);
                     let value_str = str::from_utf8_unchecked(value_slice);
 
-                    let key_str = CStr::from_ptr(localname);
-                    let attr = LocalName::from(key_str.to_str_utf8());
-                    array.push((attr, Attribute::Unterminated(value_str)));
+                    array.push((qual_name, value_str));
                 }
 
                 i += 5;
@@ -147,83 +87,51 @@ impl<'a> PropertyBag<'a> {
 }
 
 impl<'a> Iterator for PropertyBagIter<'a> {
-    type Item = (LocalName, &'a str);
+    type Item = (QualName, &'a str);
 
     fn next(&mut self) -> Option<Self::Item> {
-        self.0.next().map(|(a, v)| match *v {
-            Attribute::CStr(ref v) => (a.clone(), v.to_str_utf8()),
-            Attribute::Unterminated(v) => (a.clone(), v),
-        })
+        self.0.next().map(|(a, v)| (a.clone(), v.clone()))
     }
 }
 
 #[cfg(test)]
 mod tests {
     use super::*;
-    use markup5ever::local_name;
+    use markup5ever::{local_name, namespace_url, ns, LocalName};
     use std::ffi::CString;
     use std::ptr;
 
     #[test]
     fn empty_property_bag() {
-        let map = unsafe { PropertyBag::new_from_key_value_pairs(ptr::null()) };
+        let map = unsafe { PropertyBag::new_from_namespaced_attributes(0, ptr::null()) };
         assert_eq!(map.len(), 0);
     }
 
-    #[test]
-    fn property_bag_iters() {
-        let pairs = [
-            CString::new("rx").unwrap(),
-            CString::new("1").unwrap(),
-            CString::new("ry").unwrap(),
-            CString::new("2").unwrap(),
-        ];
-
-        let mut v = Vec::new();
-
-        for x in &pairs {
-            v.push(x.as_ptr() as *const libc::c_char);
-        }
-
-        v.push(ptr::null());
-
-        let pbag = unsafe { PropertyBag::new_from_key_value_pairs(v.as_ptr()) };
-
-        let mut had_rx: bool = false;
-        let mut had_ry: bool = false;
-
-        for (a, v) in pbag.iter() {
-            match a {
-                local_name!("rx") => {
-                    assert!(v == "1");
-                    had_rx = true;
-                }
-                local_name!("ry") => {
-                    assert!(v == "2");
-                    had_ry = true;
-                }
-                _ => unreachable!(),
-            }
-        }
-
-        assert!(had_rx);
-        assert!(had_ry);
-    }
-
     #[test]
     fn property_bag_with_namespaces() {
         let attrs = [
-            (CString::new("rx").unwrap(), CString::new("1").unwrap()),
-            (CString::new("ry").unwrap(), CString::new("2").unwrap()),
-            (CString::new("empty").unwrap(), CString::new("").unwrap()),
+            (CString::new("rx").unwrap(),
+             CString::new("svg").unwrap(),
+             CString::new("http://www.w3.org/2000/svg";).unwrap(),
+             CString::new("1").unwrap()),
+
+            (CString::new("ry").unwrap(),
+             CString::new("svg").unwrap(),
+             CString::new("http://www.w3.org/2000/svg";).unwrap(),
+             CString::new("2").unwrap()),
+
+            (CString::new("empty").unwrap(),
+             CString::new("svg").unwrap(),
+             CString::new("http://www.w3.org/2000/svg";).unwrap(),
+             CString::new("").unwrap()),
         ];
 
         let mut v: Vec<*const libc::c_char> = Vec::new();
 
-        for (key, val) in &attrs {
-            v.push(key.as_ptr() as *const libc::c_char); // localname
-            v.push(ptr::null()); // prefix
-            v.push(ptr::null()); // uri
+        for (localname, prefix, uri, val) in &attrs {
+            v.push(localname.as_ptr() as *const libc::c_char);
+            v.push(prefix.as_ptr() as *const libc::c_char);
+            v.push(uri.as_ptr() as *const libc::c_char);
 
             let val_start = val.as_ptr() as *const libc::c_char;
             let val_end = unsafe { val_start.offset(val.as_bytes().len() as isize) };
@@ -231,14 +139,17 @@ mod tests {
             v.push(val_end); // value_end
         }
 
-        let pbag = unsafe { PropertyBag::new_from_namespaced_attributes(2, v.as_ptr()) };
+        let pbag = unsafe { PropertyBag::new_from_namespaced_attributes(3, v.as_ptr()) };
 
         let mut had_rx: bool = false;
         let mut had_ry: bool = false;
         let mut had_empty: bool = false;
 
         for (a, v) in pbag.iter() {
-            match a {
+            assert_eq!(a.prefix.as_ref().unwrap(), "svg");
+            assert_eq!(a.ns, ns!(svg));
+
+            match a.local {
                 local_name!("rx") => {
                     assert!(v == "1");
                     had_rx = true;
@@ -257,5 +168,6 @@ mod tests {
 
         assert!(had_rx);
         assert!(had_ry);
+        assert!(had_empty);
     }
 }
diff --git a/rsvg_internals/src/shapes.rs b/rsvg_internals/src/shapes.rs
index 933383ca..7c2e00f1 100644
--- a/rsvg_internals/src/shapes.rs
+++ b/rsvg_internals/src/shapes.rs
@@ -1,5 +1,5 @@
 use cairo;
-use markup5ever::local_name;
+use markup5ever::{expanded_name, local_name, namespace_url, ns};
 use std::ops::Deref;
 
 use crate::bbox::BoundingBox;
@@ -120,7 +120,7 @@ pub struct NodePath {
 impl NodeTrait for NodePath {
     fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
         for (attr, value) in pbag.iter() {
-            if attr == local_name!("d") {
+            if attr.expanded() == expanded_name!(svg "d") {
                 let mut builder = PathBuilder::new();
 
                 if let Err(e) = path_parser::parse_path_into_builder(value, &mut builder) {
@@ -233,7 +233,7 @@ pub struct NodePolygon {
 impl NodeTrait for NodePolygon {
     fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
         for (attr, value) in pbag.iter() {
-            if attr == local_name!("points") {
+            if attr.expanded() == expanded_name!(svg "points") {
                 self.points = attr.parse(value.trim()).map(Some)?;
             }
         }
@@ -267,7 +267,7 @@ pub struct NodePolyline {
 impl NodeTrait for NodePolyline {
     fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
         for (attr, value) in pbag.iter() {
-            if attr == local_name!("points") {
+            if attr.expanded() == expanded_name!(svg "points") {
                 self.points = attr.parse(value.trim()).map(Some)?;
             }
         }
@@ -304,11 +304,11 @@ pub struct NodeLine {
 impl NodeTrait for NodeLine {
     fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
         for (attr, value) in pbag.iter() {
-            match attr {
-                local_name!("x1") => self.x1 = attr.parse(value)?,
-                local_name!("y1") => self.y1 = attr.parse(value)?,
-                local_name!("x2") => self.x2 = attr.parse(value)?,
-                local_name!("y2") => self.y2 = attr.parse(value)?,
+            match attr.expanded() {
+                expanded_name!(svg "x1") => self.x1 = attr.parse(value)?,
+                expanded_name!(svg "y1") => self.y1 = attr.parse(value)?,
+                expanded_name!(svg "x2") => self.x2 = attr.parse(value)?,
+                expanded_name!(svg "y2") => self.y2 = attr.parse(value)?,
                 _ => (),
             }
         }
@@ -356,21 +356,21 @@ pub struct NodeRect {
 impl NodeTrait for NodeRect {
     fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
         for (attr, value) in pbag.iter() {
-            match attr {
-                local_name!("x") => self.x = attr.parse(value)?,
-                local_name!("y") => self.y = attr.parse(value)?,
-                local_name!("width") => {
+            match attr.expanded() {
+                expanded_name!(svg "x") => self.x = attr.parse(value)?,
+                expanded_name!(svg "y") => self.y = attr.parse(value)?,
+                expanded_name!(svg "width") => {
                     self.w = attr.parse_and_validate(value, LengthHorizontal::check_nonnegative)?
                 }
-                local_name!("height") => {
+                expanded_name!(svg "height") => {
                     self.h = attr.parse_and_validate(value, LengthVertical::check_nonnegative)?
                 }
-                local_name!("rx") => {
+                expanded_name!(svg "rx") => {
                     self.rx = attr
                         .parse_and_validate(value, LengthHorizontal::check_nonnegative)
                         .map(Some)?
                 }
-                local_name!("ry") => {
+                expanded_name!(svg "ry") => {
                     self.ry = attr
                         .parse_and_validate(value, LengthVertical::check_nonnegative)
                         .map(Some)?
@@ -572,10 +572,10 @@ pub struct NodeCircle {
 impl NodeTrait for NodeCircle {
     fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
         for (attr, value) in pbag.iter() {
-            match attr {
-                local_name!("cx") => self.cx = attr.parse(value)?,
-                local_name!("cy") => self.cy = attr.parse(value)?,
-                local_name!("r") => {
+            match attr.expanded() {
+                expanded_name!(svg "cx") => self.cx = attr.parse(value)?,
+                expanded_name!(svg "cy") => self.cy = attr.parse(value)?,
+                expanded_name!(svg "r") => {
                     self.r = attr.parse_and_validate(value, LengthBoth::check_nonnegative)?
                 }
                 _ => (),
@@ -615,13 +615,13 @@ pub struct NodeEllipse {
 impl NodeTrait for NodeEllipse {
     fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
         for (attr, value) in pbag.iter() {
-            match attr {
-                local_name!("cx") => self.cx = attr.parse(value)?,
-                local_name!("cy") => self.cy = attr.parse(value)?,
-                local_name!("rx") => {
+            match attr.expanded() {
+                expanded_name!(svg "cx") => self.cx = attr.parse(value)?,
+                expanded_name!(svg "cy") => self.cy = attr.parse(value)?,
+                expanded_name!(svg "rx") => {
                     self.rx = attr.parse_and_validate(value, LengthHorizontal::check_nonnegative)?
                 }
-                local_name!("ry") => {
+                expanded_name!(svg "ry") => {
                     self.ry = attr.parse_and_validate(value, LengthVertical::check_nonnegative)?
                 }
                 _ => (),
diff --git a/rsvg_internals/src/structure.rs b/rsvg_internals/src/structure.rs
index b8c59ca1..5ffbc96d 100644
--- a/rsvg_internals/src/structure.rs
+++ b/rsvg_internals/src/structure.rs
@@ -1,5 +1,5 @@
 use cairo::Rectangle;
-use markup5ever::local_name;
+use markup5ever::{expanded_name, local_name, namespace_url, ns};
 
 use crate::allowed_url::Fragment;
 use crate::aspect_ratio::*;
@@ -181,21 +181,21 @@ impl NodeTrait for NodeSvg {
         let is_inner_svg = parent.is_some();
 
         for (attr, value) in pbag.iter() {
-            match attr {
-                local_name!("preserveAspectRatio") => {
+            match attr.expanded() {
+                expanded_name!(svg "preserveAspectRatio") => {
                     self.preserve_aspect_ratio = attr.parse(value)?
                 }
-                local_name!("x") if is_inner_svg => self.x = Some(attr.parse(value)?),
-                local_name!("y") if is_inner_svg => self.y = Some(attr.parse(value)?),
-                local_name!("width") => {
+                expanded_name!(svg "x") if is_inner_svg => self.x = Some(attr.parse(value)?),
+                expanded_name!(svg "y") if is_inner_svg => self.y = Some(attr.parse(value)?),
+                expanded_name!(svg "width") => {
                     self.w =
                         Some(attr.parse_and_validate(value, LengthHorizontal::check_nonnegative)?)
                 }
-                local_name!("height") => {
+                expanded_name!(svg "height") => {
                     self.h =
                         Some(attr.parse_and_validate(value, LengthVertical::check_nonnegative)?)
                 }
-                local_name!("viewBox") => self.vbox = attr.parse(value).map(Some)?,
+                expanded_name!(svg "viewBox") => self.vbox = attr.parse(value).map(Some)?,
                 _ => (),
             }
         }
@@ -275,18 +275,18 @@ pub struct NodeUse {
 impl NodeTrait for NodeUse {
     fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
         for (attr, value) in pbag.iter() {
-            match attr {
-                local_name!("xlink:href") => {
+            match attr.expanded() {
+                expanded_name!(xlink "href") => {
                     self.link = Some(Fragment::parse(value).attribute(attr)?)
                 }
-                local_name!("x") => self.x = attr.parse(value)?,
-                local_name!("y") => self.y = attr.parse(value)?,
-                local_name!("width") => {
+                expanded_name!(svg "x") => self.x = attr.parse(value)?,
+                expanded_name!(svg "y") => self.y = attr.parse(value)?,
+                expanded_name!(svg "width") => {
                     self.w = attr
                         .parse_and_validate(value, LengthHorizontal::check_nonnegative)
                         .map(Some)?
                 }
-                local_name!("height") => {
+                expanded_name!(svg "height") => {
                     self.h = attr
                         .parse_and_validate(value, LengthVertical::check_nonnegative)
                         .map(Some)?
@@ -428,11 +428,11 @@ pub struct NodeSymbol {
 impl NodeTrait for NodeSymbol {
     fn set_atts(&mut self, _parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
         for (attr, value) in pbag.iter() {
-            match attr {
-                local_name!("preserveAspectRatio") => {
+            match attr.expanded() {
+                expanded_name!(svg "preserveAspectRatio") => {
                     self.preserve_aspect_ratio = attr.parse(value)?
                 }
-                local_name!("viewBox") => self.vbox = attr.parse(value).map(Some)?,
+                expanded_name!(svg "viewBox") => self.vbox = attr.parse(value).map(Some)?,
                 _ => (),
             }
         }
diff --git a/rsvg_internals/src/style.rs b/rsvg_internals/src/style.rs
index fe290892..501fb3ea 100644
--- a/rsvg_internals/src/style.rs
+++ b/rsvg_internals/src/style.rs
@@ -1,4 +1,4 @@
-use markup5ever::local_name;
+use markup5ever::{expanded_name, local_name, namespace_url, ns};
 
 use crate::node::{NodeResult, NodeTrait, NodeType, RsvgNode};
 use crate::property_bag::PropertyBag;
@@ -45,7 +45,7 @@ impl NodeStyle {
 impl NodeTrait for NodeStyle {
     fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
         for (attr, value) in pbag.iter() {
-            if attr == local_name!("type") {
+            if attr.expanded() == expanded_name!(svg "type") {
                 self.type_ = Some(value.to_string());
             }
         }
diff --git a/rsvg_internals/src/text.rs b/rsvg_internals/src/text.rs
index dd076377..06facd5d 100644
--- a/rsvg_internals/src/text.rs
+++ b/rsvg_internals/src/text.rs
@@ -1,5 +1,5 @@
 use glib::translate::*;
-use markup5ever::local_name;
+use markup5ever::{expanded_name, local_name, namespace_url, ns};
 use pango::{self, FontMapExt};
 use pango_sys;
 use pangocairo;
@@ -593,11 +593,11 @@ impl NodeText {
 impl NodeTrait for NodeText {
     fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
         for (attr, value) in pbag.iter() {
-            match attr {
-                local_name!("x") => self.x = attr.parse(value)?,
-                local_name!("y") => self.y = attr.parse(value)?,
-                local_name!("dx") => self.dx = attr.parse(value).map(Some)?,
-                local_name!("dy") => self.dy = attr.parse(value).map(Some)?,
+            match attr.expanded() {
+                expanded_name!(svg "x") => self.x = attr.parse(value)?,
+                expanded_name!(svg "y") => self.y = attr.parse(value)?,
+                expanded_name!(svg "dx") => self.dx = attr.parse(value).map(Some)?,
+                expanded_name!(svg "dy") => self.dy = attr.parse(value).map(Some)?,
                 _ => (),
             }
         }
@@ -711,8 +711,8 @@ fn extract_chars_children_to_chunks_recursively(
 impl NodeTrait for NodeTRef {
     fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
         for (attr, value) in pbag.iter() {
-            match attr {
-                local_name!("xlink:href") => {
+            match attr.expanded() {
+                expanded_name!(xlink "href") => {
                     self.link = Some(Fragment::parse(value).attribute(attr)?)
                 }
                 _ => (),
@@ -753,11 +753,11 @@ impl NodeTSpan {
 impl NodeTrait for NodeTSpan {
     fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
         for (attr, value) in pbag.iter() {
-            match attr {
-                local_name!("x") => self.x = attr.parse(value).map(Some)?,
-                local_name!("y") => self.y = attr.parse(value).map(Some)?,
-                local_name!("dx") => self.dx = attr.parse(value).map(Some)?,
-                local_name!("dy") => self.dy = attr.parse(value).map(Some)?,
+            match attr.expanded() {
+                expanded_name!(svg "x") => self.x = attr.parse(value).map(Some)?,
+                expanded_name!(svg "y") => self.y = attr.parse(value).map(Some)?,
+                expanded_name!(svg "dx") => self.dx = attr.parse(value).map(Some)?,
+                expanded_name!(svg "dy") => self.dy = attr.parse(value).map(Some)?,
                 _ => (),
             }
         }
diff --git a/rsvg_internals/src/util.rs b/rsvg_internals/src/util.rs
index 6637bdef..2116cb6a 100644
--- a/rsvg_internals/src/util.rs
+++ b/rsvg_internals/src/util.rs
@@ -4,6 +4,8 @@ use std::borrow::Cow;
 use std::ffi::CStr;
 use std::str;
 
+use markup5ever::{namespace_url, ns, LocalName, Namespace, Prefix, QualName};
+
 /// Converts a `char *` which is known to be valid UTF-8 into a `&str`
 ///
 /// The usual `from_glib_none(s)` allocates an owned String.  The
@@ -16,6 +18,14 @@ pub unsafe fn utf8_cstr<'a>(s: *const libc::c_char) -> &'a str {
     str::from_utf8_unchecked(CStr::from_ptr(s).to_bytes())
 }
 
+pub unsafe fn opt_utf8_cstr<'a>(s: *const libc::c_char) -> Option<&'a str> {
+    if s.is_null() {
+        None
+    } else {
+        Some(utf8_cstr(s))
+    }
+}
+
 /// Error-tolerant C string import
 pub unsafe fn cstr<'a>(s: *const libc::c_char) -> Cow<'a, str> {
     if s.is_null() {
@@ -33,3 +43,25 @@ pub fn clamp<T: PartialOrd>(val: T, low: T, high: T) -> T {
         val
     }
 }
+
+pub fn make_qual_name(prefix: Option<&str>, uri: Option<&str>, localname: &str) -> QualName {
+    let ns = if let Some(uri) = uri {
+        Namespace::from(uri)
+    } else {
+        // FIXME: This assumes that unprefixed attribute names default to the svg namespace.
+        // I.e. <foo bar="baz"/> would yield an svg:bar attribute.
+        //
+        // I'm not sure if this is how things are supposed to work if there is
+        // a second namespace embedded in the middle of SVG markup:
+        //
+        // <svg xmlns="http://www.w3.org/2000/svg";>
+        //   <g>
+        //     <something xmlns="http://example.com/something";>
+        //       <somethingelse foo="blah"/>
+        //                      ^^^ should this be assumed something:foo?
+        ns!(svg)
+    };
+
+    QualName::new(prefix.map(Prefix::from), ns, LocalName::from(localname))
+}
+
diff --git a/rsvg_internals/src/xml.rs b/rsvg_internals/src/xml.rs
index c2afa3ec..40646fd9 100644
--- a/rsvg_internals/src/xml.rs
+++ b/rsvg_internals/src/xml.rs
@@ -2,7 +2,7 @@ use crate::xml_rs::{reader::XmlEvent, ParserConfig};
 use encoding::label::encoding_from_whatwg_label;
 use encoding::DecoderTrap;
 use libc;
-use markup5ever::{local_name, LocalName, Namespace, QualName};
+use markup5ever::{ExpandedName, LocalName, Namespace, QualName};
 use std::cell::RefCell;
 use std::collections::HashMap;
 use std::rc::{Rc, Weak};
@@ -58,6 +58,19 @@ extern "C" {
     fn xmlFreeNode(node: XmlEntityPtr);
 }
 
+// Creates an ExpandedName from the XInclude namespace and a local_name
+//
+// The markup5ever crate doesn't have built-in namespaces for XInclude,
+// so we make our own.
+macro_rules! xinclude_name {
+    ($local_name:expr) => {
+        ExpandedName {
+            ns: &Namespace::from("http://www.w3.org/2001/XInclude";),
+            local: &LocalName::from($local_name),
+        }
+    };
+}
+
 /// Holds the state used for XML processing
 ///
 /// These methods are called when an XML event is parsed out of the XML stream: `start_element`,
@@ -168,7 +181,7 @@ impl XmlState {
         }
     }
 
-    pub fn start_element(&self, name: &str, pbag: &PropertyBag) -> Result<(), ()> {
+    pub fn start_element(&self, name: QualName, pbag: &PropertyBag) -> Result<(), ()> {
         self.check_limits()?;
 
         let context = self.inner.borrow().context();
@@ -179,16 +192,13 @@ impl XmlState {
 
         self.inner.borrow_mut().num_loaded_elements += 1;
 
-        // FIXME: we should deal with namespaces at some point
-        let name = skip_namespace(name);
-
         let new_context = match context {
-            Context::Start => self.element_creation_start_element(name, pbag),
-            Context::ElementCreation => self.element_creation_start_element(name, pbag),
-            Context::XInclude(ref ctx) => self.inside_xinclude_start_element(&ctx, name),
-            Context::UnsupportedXIncludeChild => self.unsupported_xinclude_start_element(name),
+            Context::Start => self.element_creation_start_element(&name, pbag),
+            Context::ElementCreation => self.element_creation_start_element(&name, pbag),
+            Context::XInclude(ref ctx) => self.inside_xinclude_start_element(&ctx, &name),
+            Context::UnsupportedXIncludeChild => self.unsupported_xinclude_start_element(&name),
             Context::XIncludeFallback(ref ctx) => {
-                self.xinclude_fallback_start_element(&ctx, name, pbag)
+                self.xinclude_fallback_start_element(&ctx, &name, pbag)
             }
 
             Context::FatalError(_) => unreachable!(),
@@ -199,7 +209,7 @@ impl XmlState {
         Ok(())
     }
 
-    pub fn end_element(&self, _name: &str) {
+    pub fn end_element(&self, _name: QualName) {
         let context = self.inner.borrow().context();
 
         match context {
@@ -301,33 +311,32 @@ impl XmlState {
         }
     }
 
-    fn element_creation_start_element(&self, name: &str, pbag: &PropertyBag) -> Context {
-        match name {
-            "include" => self.xinclude_start_element(name, pbag),
-            _ => {
-                let mut inner = self.inner.borrow_mut();
-
-                let ids = inner.ids.as_mut().unwrap();
-                let mut node = create_node_and_register_id(name, pbag, ids);
+    fn element_creation_start_element(&self, name: &QualName, pbag: &PropertyBag) -> Context {
+        if name.expanded() == xinclude_name!("include") {
+            self.xinclude_start_element(name, pbag)
+        } else {
+            let mut inner = self.inner.borrow_mut();
 
-                let parent = inner.current_node.clone();
-                node.borrow_mut()
-                    .set_atts(parent.as_ref(), pbag, self.load_options.locale());
+            let ids = inner.ids.as_mut().unwrap();
+            let mut node = create_node_and_register_id(name, pbag, ids);
 
-                if let Some(mut parent) = parent {
-                    parent.append(node.clone());
-                } else {
-                    if inner.tree_root.is_some() {
-                        panic!("The tree root has already been set");
-                    }
+            let parent = inner.current_node.clone();
+            node.borrow_mut()
+                .set_atts(parent.as_ref(), pbag, self.load_options.locale());
 
-                    inner.tree_root = Some(node.clone());
+            if let Some(mut parent) = parent {
+                parent.append(node.clone());
+            } else {
+                if inner.tree_root.is_some() {
+                    panic!("The tree root has already been set");
                 }
 
-                inner.current_node = Some(node);
-
-                Context::ElementCreation
+                inner.tree_root = Some(node.clone());
             }
+
+            inner.current_node = Some(node);
+
+            Context::ElementCreation
         }
     }
 
@@ -362,7 +371,7 @@ impl XmlState {
         } else {
             let child = RsvgNode::new(NodeData::new(
                 NodeType::Chars,
-                QualName::new(
+                &QualName::new(
                     None,
                     Namespace::from("https://wiki.gnome.org/Projects/LibRsvg";),
                     LocalName::from("rsvg-chars"),
@@ -381,16 +390,16 @@ impl XmlState {
         chars_node.borrow().get_impl::<NodeChars>().append(text);
     }
 
-    fn xinclude_start_element(&self, _name: &str, pbag: &PropertyBag) -> Context {
+    fn xinclude_start_element(&self, _name: &QualName, pbag: &PropertyBag) -> Context {
         let mut href = None;
         let mut parse = None;
         let mut encoding = None;
 
         for (attr, value) in pbag.iter() {
-            match attr {
-                local_name!("href") => href = Some(value),
-                ref n if *n == LocalName::from("parse") => parse = Some(value),
-                local_name!("encoding") => encoding = Some(value),
+            match attr.expanded() {
+                ref n if *n == xinclude_name!("href") => href = Some(value),
+                ref n if *n == xinclude_name!("parse") => parse = Some(value),
+                ref n if *n == xinclude_name!("encoding") => encoding = Some(value),
                 _ => (),
             }
         }
@@ -406,9 +415,8 @@ impl XmlState {
         Context::XInclude(XIncludeContext { need_fallback })
     }
 
-    fn inside_xinclude_start_element(&self, ctx: &XIncludeContext, name: &str) -> Context {
-        // FIXME: we aren't using the xi: namespace
-        if name == "fallback" {
+    fn inside_xinclude_start_element(&self, ctx: &XIncludeContext, name: &QualName) -> Context {
+        if name.expanded() == xinclude_name!("fallback") {
             Context::XIncludeFallback(ctx.clone())
         } else {
             // https://www.w3.org/TR/xinclude/#include_element
@@ -426,12 +434,11 @@ impl XmlState {
     fn xinclude_fallback_start_element(
         &self,
         ctx: &XIncludeContext,
-        name: &str,
+        name: &QualName,
         pbag: &PropertyBag,
     ) -> Context {
         if ctx.need_fallback {
-            // FIXME: we aren't using the xi: namespace
-            if name == "include" {
+            if name.expanded() == xinclude_name!("include") {
                 self.xinclude_start_element(name, pbag)
             } else {
                 self.element_creation_start_element(name, pbag)
@@ -568,7 +575,7 @@ impl XmlState {
         .and_then(|_: ()| self.check_last_error())
     }
 
-    fn unsupported_xinclude_start_element(&self, _name: &str) -> Context {
+    fn unsupported_xinclude_start_element(&self, _name: &QualName) -> Context {
         Context::UnsupportedXIncludeChild
     }
 }
@@ -585,10 +592,6 @@ impl Drop for XmlState {
     }
 }
 
-fn skip_namespace(s: &str) -> &str {
-    s.find(':').map_or(s, |pos| &s[pos + 1..])
-}
-
 // https://www.w3.org/TR/xml-stylesheet/
 //
 // The syntax for the xml-stylesheet processing instruction we support
@@ -638,15 +641,3 @@ pub fn xml_load_from_possibly_compressed_stream(
 
     state.steal_result()
 }
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-
-    #[test]
-    fn skips_namespaces() {
-        assert_eq!(skip_namespace("foo"), "foo");
-        assert_eq!(skip_namespace("foo:bar"), "bar");
-        assert_eq!(skip_namespace("foo:bar:baz"), "bar:baz");
-    }
-}
diff --git a/rsvg_internals/src/xml2_load.rs b/rsvg_internals/src/xml2_load.rs
index 12e60267..8d942178 100644
--- a/rsvg_internals/src/xml2_load.rs
+++ b/rsvg_internals/src/xml2_load.rs
@@ -15,8 +15,7 @@ use glib::translate::*;
 
 use crate::error::LoadingError;
 use crate::property_bag::PropertyBag;
-use crate::util::cstr;
-use crate::util::utf8_cstr;
+use crate::util::{cstr, make_qual_name, opt_utf8_cstr, utf8_cstr};
 use crate::xml::XmlState;
 use crate::xml2::*;
 
@@ -178,23 +177,26 @@ unsafe extern "C" fn sax_start_element_ns_cb(
     localname: *mut libc::c_char,
     prefix: *mut libc::c_char,
     uri: *mut libc::c_char,
-    nb_namespaces: libc::c_int,
-    namespaces: *mut *mut libc::c_char,
+    _nb_namespaces: libc::c_int,
+    _namespaces: *mut *mut libc::c_char,
     nb_attributes: libc::c_int,
-    nb_defaulted: libc::c_int,
+    _nb_defaulted: libc::c_int,
     attributes: *mut *mut libc::c_char,
 ) {
     let xml2_parser = &*(user_data as *mut Xml2Parser);
 
     assert!(!localname.is_null());
 
+    let prefix = opt_utf8_cstr(prefix);
+    let uri = opt_utf8_cstr(uri);
     let localname = utf8_cstr(localname);
+    let qual_name = make_qual_name(prefix, uri, localname);
 
     let nb_attributes = nb_attributes as usize;
     let pbag =
         PropertyBag::new_from_namespaced_attributes(nb_attributes, attributes as *const *const _);
 
-    if let Err(e) = xml2_parser.state.start_element(localname, &pbag) {
+    if let Err(e) = xml2_parser.state.start_element(qual_name, &pbag) {
         let _: () = e; // guard in case we change the error type later
 
         let parser = xml2_parser.parser.get();
@@ -211,9 +213,13 @@ unsafe extern "C" fn sax_end_element_ns_cb(
     let xml2_parser = &*(user_data as *mut Xml2Parser);
 
     assert!(!localname.is_null());
+
+    let prefix = opt_utf8_cstr(prefix);
+    let uri = opt_utf8_cstr(uri);
     let localname = utf8_cstr(localname);
+    let qual_name = make_qual_name(prefix, uri, localname);
 
-    xml2_parser.state.end_element(localname);
+    xml2_parser.state.end_element(qual_name);
 }
 
 unsafe extern "C" fn sax_characters_cb(


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]