Skip to content

Commit

Permalink
Support aliased namespace prefixes
Browse files Browse the repository at this point in the history
Fixes r-lib#35
  • Loading branch information
jimhester committed May 31, 2016
1 parent d7b883d commit d4807bb
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 30 deletions.
42 changes: 14 additions & 28 deletions src/xml2_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,9 @@ class Xml2String {
class NsMap {

// We only store the index to avoid duplicating the data
typedef boost::unordered_map<std::string, std::string> url2prefix_t;
typedef std::multimap<std::string, std::string> prefix2url_t;

url2prefix_t url2prefix;
std::vector<std::string> order;
prefix2url_t prefix2url;

public:
NsMap() {
Expand All @@ -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();
}

Expand All @@ -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<std::string> name;
name.reserve(order.size());

for(std::vector<std::string>::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
4 changes: 4 additions & 0 deletions tests/testthat/ns-multiple-aliases.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<root>
<doc1 xmlns:b="http://bar.com"><b:bar /></doc1>
<doc2 xmlns:c="http://bar.com"><c:bar /></doc2>
</root>
9 changes: 7 additions & 2 deletions tests/testthat/test-namespaces.R
Original file line number Diff line number Diff line change
Expand Up @@ -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 ---------------------------------------------

Expand All @@ -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", {
Expand Down

0 comments on commit d4807bb

Please sign in to comment.