Generate a namespace prefix for unprefixed attributes in namespaces. It's a start, but needs to check for clashes. I also wonder if there are cases when I need to generate them for elements too. Hmmm

This commit is contained in:
Jez Higgins 2010-07-14 22:36:05 +01:00
parent 7080c5049e
commit abaaaf4cc4
2 changed files with 53 additions and 6 deletions

View file

@ -69,12 +69,14 @@ std::pair<bool, stringT> is_uri_declared(std::vector<std::map<stringT, stringT>
} // for ...
return std::make_pair(false, stringT());
} // prefix_is_declared
} // is_uri_declared
template<class stringT, class string_adaptorT, class charT, class traitsT>
void check_and_output_node_name(std::basic_ostream<charT, traitsT>& stream,
const DOM::Node<stringT, string_adaptorT>& node,
std::vector<std::map<stringT, stringT> >* prefix_stack)
std::vector<std::map<stringT, stringT> >* prefix_stack,
const bool is_attribute,
const long index)
{
std::map<stringT, stringT>& current = *(prefix_stack->rbegin());
@ -84,7 +86,15 @@ void check_and_output_node_name(std::basic_ostream<charT, traitsT>& stream,
std::pair<bool, stringT> prefix = is_uri_declared(prefix_stack, namespaceURI);
if(!prefix.first)
current[namespaceURI] = prefix.second = node.getPrefix();
{
current[namespaceURI] = prefix.second = node.getPrefix();
if(is_attribute && string_adaptorT::empty(prefix.second))
{
std::ostringstream os;
os << 'a' << stream.iword(index)++;
current[namespaceURI] = prefix.second = os.str();
} // if ...
} // if ...
if(!string_adaptorT::empty(prefix.second))
stream << prefix.second << Arabica::text::Unicode<charT>::COLON;
@ -131,6 +141,7 @@ int prefix_mapper(std::basic_ostream<charT, traitsT>& stream,
{
prefix_stack = new std::vector<std::map<stringT, stringT> >;
stream.pword(index) = prefix_stack;
stream.iword(index) = 0;
std::map<stringT, stringT> prefixes;
for(DOM::Node<stringT, string_adaptorT> p = node.getParentNode();
@ -149,7 +160,7 @@ int prefix_mapper(std::basic_ostream<charT, traitsT>& stream,
std::map<stringT, stringT>& current = *(prefix_stack->rbegin());
// is element namespace URI declared?
check_and_output_node_name(stream, node, prefix_stack);
check_and_output_node_name(stream, node, prefix_stack, false, index);
DOM::NamedNodeMap<stringT, string_adaptorT> attrs = node.getAttributes();
std::vector<stringT> names;
@ -164,7 +175,7 @@ int prefix_mapper(std::basic_ostream<charT, traitsT>& stream,
isXmlns<stringT, string_adaptorT, charT>(attr.getPrefix()))
continue;
stream << UnicodeT::SPACE;
check_and_output_node_name(stream, attr, prefix_stack);
check_and_output_node_name(stream, attr, prefix_stack, true, index);
stream << UnicodeT::EQUALS_SIGN
<< UnicodeT::QUOTATION_MARK;
stringT value = attr.getNodeValue();
@ -206,7 +217,7 @@ void prefix_mapper_pop(std::basic_ostream<charT, traitsT>& stream,
static_cast<std::vector<std::map<stringT, stringT> >*>(stream.pword(index));
if(output)
check_and_output_node_name(stream, node, prefix_stack);
check_and_output_node_name(stream, node, prefix_stack, false, index);
prefix_stack->pop_back();
if(prefix_stack->empty())

View file

@ -173,6 +173,40 @@ public:
stream << a;
assertEquals(s("<a xmlns=\"urn:test\"><b a0:x=\"y\" xmlns:a0=\"urn:case\"><c/></b></a>"), s(stream.str().c_str()), __LINE__);
} // testNSPrefixAttrNS3
void testNSPrefixAttrNS4()
{
DocumentT doc = factory.createDocument(s("urn:test"), s("a"), 0);
ElementT a = doc.getDocumentElement();
ElementT b = doc.createElementNS(s("urn:test"), s("b"));
b.setAttributeNS(s("urn:case"), s("x"), s("y"));
b.setAttributeNS(s("urn:box"), s("z"), s("y"));
ElementT c = doc.createElementNS(s("urn:test"), s("c"));
a.appendChild(b);
b.appendChild(c);
stringstreamT stream;
stream << a;
assertEquals(s("<a xmlns=\"urn:test\"><b a0:x=\"y\" a1:z=\"y\" xmlns:a1=\"urn:box\" xmlns:a0=\"urn:case\"><c/></b></a>"), s(stream.str().c_str()), __LINE__);
} // testNSPrefixAttrNS4
void testNSPrefixAttrNS5()
{
DocumentT doc = factory.createDocument(s("urn:test"), s("a"), 0);
ElementT a = doc.getDocumentElement();
ElementT b = doc.createElementNS(s("urn:test"), s("b"));
b.setAttributeNS(s("urn:case"), s("x"), s("y"));
b.setAttributeNS(s("urn:box"), s("x"), s("y"));
ElementT c = doc.createElementNS(s("urn:test"), s("c"));
a.appendChild(b);
b.appendChild(c);
stringstreamT stream;
stream << a;
assertEquals(s("<a xmlns=\"urn:test\"><b a0:x=\"y\" a1:x=\"y\" xmlns:a1=\"urn:box\" xmlns:a0=\"urn:case\"><c/></b></a>"), s(stream.str().c_str()), __LINE__);
} // testNSPrefixAttrNS5
}; // class StreamTest
template<class string_type, class string_adaptor>
@ -187,6 +221,8 @@ TestSuite* StreamTest_suite()
suiteOfTests->addTest(new TestCaller<StreamTest<string_type, string_adaptor> >("testNSPrefixAttrNS", &StreamTest<string_type, string_adaptor>::testNSPrefixAttrNS));
suiteOfTests->addTest(new TestCaller<StreamTest<string_type, string_adaptor> >("testNSPrefixAttrNS2", &StreamTest<string_type, string_adaptor>::testNSPrefixAttrNS2));
suiteOfTests->addTest(new TestCaller<StreamTest<string_type, string_adaptor> >("testNSPrefixAttrNS3", &StreamTest<string_type, string_adaptor>::testNSPrefixAttrNS3));
suiteOfTests->addTest(new TestCaller<StreamTest<string_type, string_adaptor> >("testNSPrefixAttrNS4", &StreamTest<string_type, string_adaptor>::testNSPrefixAttrNS4));
suiteOfTests->addTest(new TestCaller<StreamTest<string_type, string_adaptor> >("testNSPrefixAttrNS5", &StreamTest<string_type, string_adaptor>::testNSPrefixAttrNS5));
return suiteOfTests;
} // StreamTest_suite