From d4807bb55065c40c6eb8f7e95b8dc03a00ffae16 Mon Sep 17 00:00:00 2001 From: Jim Hester Date: Tue, 31 May 2016 10:28:30 -0400 Subject: [PATCH] Support aliased namespace prefixes Fixes #35 --- src/xml2_utils.h | 42 +++++++++----------------- tests/testthat/ns-multiple-aliases.xml | 4 +++ tests/testthat/test-namespaces.R | 9 ++++-- 3 files changed, 25 insertions(+), 30 deletions(-) create mode 100644 tests/testthat/ns-multiple-aliases.xml diff --git a/src/xml2_utils.h b/src/xml2_utils.h index 29cf955c..760079dd 100644 --- a/src/xml2_utils.h +++ b/src/xml2_utils.h @@ -59,10 +59,9 @@ class Xml2String { class NsMap { // We only store the index to avoid duplicating the data - typedef boost::unordered_map url2prefix_t; + typedef std::multimap prefix2url_t; - url2prefix_t url2prefix; - std::vector order; + prefix2url_t prefix2url; public: NsMap() { @@ -76,28 +75,28 @@ class NsMap { } } - bool hasUrl(std::string url) { - return url2prefix.find(url) != url2prefix.end(); + bool hasPrefix(const std::string& prefix) { + return prefix2url.find(prefix) != prefix2url.end(); } - std::string findPrefix(std::string url) { - url2prefix_t::const_iterator it = url2prefix.find(url); - if (it != url2prefix.end()) { + std::string findUrl(const std::string& prefix) { + prefix2url_t::const_iterator it = prefix2url.find(prefix); + if (it != prefix2url.end()) { return it->second; } - Rcpp::stop("Couldn't find prefix for url %s", url); + Rcpp::stop("Couldn't find url for prefix %s", prefix); return std::string(); } - std::string findUrl(std::string prefix) { - for (url2prefix_t::const_iterator it = url2prefix.begin(); it != url2prefix.end(); ++it) { - if (it->second == prefix) { + std::string findPrefix(const std::string& url) { + for (prefix2url_t::const_iterator it = prefix2url.begin(); it != prefix2url.end(); ++it) { + if (it->second == url) { return it->first; } } - Rcpp::stop("Couldn't find url for prefix %s", prefix); + Rcpp::stop("Couldn't find prefix for url %s", url); return std::string(); } @@ -106,25 +105,12 @@ class NsMap { } bool add(std::string prefix, std::string url) { - if (hasUrl(url)) - return false; - - // Add the value to the vector and store the order. - order.push_back(url); - url2prefix.insert(url2prefix_t::value_type(url, prefix)); + prefix2url.insert(prefix2url_t::value_type(prefix, url)); return true; } Rcpp::CharacterVector out() { - Rcpp::CharacterVector out = Rcpp::wrap(order); - std::vector name; - name.reserve(order.size()); - - for(std::vector::const_iterator it = order.begin();it != order.end(); ++it) { - name.push_back(url2prefix.at(*it)); - } - out.attr("names") = Rcpp::wrap(name); - return out; + return Rcpp::wrap(prefix2url); } }; #endif diff --git a/tests/testthat/ns-multiple-aliases.xml b/tests/testthat/ns-multiple-aliases.xml new file mode 100644 index 00000000..bc14cf9b --- /dev/null +++ b/tests/testthat/ns-multiple-aliases.xml @@ -0,0 +1,4 @@ + + + + diff --git a/tests/testthat/test-namespaces.R b/tests/testthat/test-namespaces.R index 44904b80..24bb5fec 100644 --- a/tests/testthat/test-namespaces.R +++ b/tests/testthat/test-namespaces.R @@ -12,6 +12,11 @@ test_that("repeated prefixes given unique names", { expect_equal(ns, c(b = "http://baz.com", b1 = "http://bar.com")) }) +test_that("aliased prefixes retained", { + ns <- unclass(xml_ns(read_xml("ns-multiple-aliases.xml"))) + expect_equal(ns, c(b = "http://bar.com", c = "http://bar.com")) +}) + # Low-level character vector tests --------------------------------------------- @@ -20,9 +25,9 @@ test_that("unique prefix-url combo unchanged", { expect_equal(unique_ns(x), x) }) -test_that("first prefix kept", { +test_that("all prefixs kept", { x <- c(blah = "http://blah.com", rah = "http://blah.com") - expect_equal(names(unique_ns(x)), "blah") + expect_equal(names(unique_ns(x)), c("blah", "rah")) }) test_that("multiple default namespaces can be stripped", {