Есть ли способ удалить пространства имен из тегов XML с помощью C ++ / Boost или с помощью какой-либо другой библиотеки

Есть ли способ в C ++, с помощью TinyXML , TinyXpath , такой, что строка содержащий:

<ns:abcd>
<ns:defg>
<ns:hijk>
</ns:hijk>
</ns:defg>
</ns:abcd>

превращается в

<abcd>
<defg>
<hijk>
</hijk>
</defg>
</abcd>

РЕДАКТИРОВАТЬ:

Я использовал Tinyxml и Tinyxpath.

Мой рабочий процесс был:

а) Создайте доменное дерево, используя TinyXML

б) Передача Dom-дерева в Tinyxpath для оценки xpath

Чтобы добавить удаление пространства имен, я использовал следующую функцию:

void  RemoveAllNamespaces(TiXmlNode* node)
{
TiXmlElement* element = node->ToElement();
if(!element){
return;
}
std::string elementName = element->Value();
std::string::size_type idx = elementName.rfind(':');
if(idx != std::string::npos)
{
element->SetValue(elementName.substr( idx + 1).c_str());
}
TiXmlNode* child = element->IterateChildren(NULL);
while(child)
{
RemoveAllNamespaces(child);
child = element->IterateChildren(child);
}
}

Поэтому рабочий процесс изменился на:

а) Создайте доменное дерево, используя TinyXML

б) Удалить пространство имен из domtree, используя RemoveAllNamespaces(domtree.Root() )

c) Передать дерево измененных доменных имен в Tinyxpath для оценки xpath

1

Решение

Хорошо, в ответ на отредактированный вопрос, несколько примечаний:

  • это на самом деле не обрабатывает пространства имен (рассмотрим xmlns="http://blabla.com/uri" стиль имен по умолчанию), но на самом деле это ограничение TinyXml (eek):

    Кроме того, TinyXML не имеет средств для обработки пространств имен XML. Квалифицированные имена элементов или атрибутов сохраняют свои префиксы, поскольку TinyXML не предпринимает никаких усилий, чтобы сопоставить префиксы с пространствами имен.

  • это не относится к атрибутам (которые также могут быть уточнены)

Вот что я бы сделал быстро & грязный (предполагается, что TIXML_USE_STL, как вы, возможно, уже использовали):

static inline std::string RemoveNs(std::string const& xmlName)
{
return xmlName.substr(xmlName.find_last_of(":") + 1);
}

void  RemoveAllNamespaces(TiXmlNode* node)
{
assert(node);

if (auto element = node->ToElement()) {
element->SetValue(RemoveNs(element->Value()));

for (auto attr = element->FirstAttribute(); attr; attr = attr->Next())
attr->SetName(RemoveNs(attr->Name()));

for (auto child = node->IterateChildren(nullptr); child; child = element->IterateChildren(child))
RemoveAllNamespaces(child);
}
}

На мой тест MSVC это печатает

<?xml version="1.0" standalone="no"?>
<!-- Our: to do list data -->
<ToDo a="http://example.org/uri1">
<!-- Do I need: a secure PDA? -->
<Item priority="1" distance="close">Go to the<bold>Toy store!</bold></Item>
<Item priority="2" distance="none">Do bills</Item>
<Item priority="2" distance="far &amp; back">Look for Evil Dinosaurs!</Item>
</ToDo>
1

Другие решения

Я бы использовал XSLT-преобразование здесь:

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output omit-xml-declaration="yes" indent="yes" />

<xsl:template match="*">
<xsl:element name="{name()}" namespace=""><xsl:apply-templates select="node()|@*"/></xsl:element>
</xsl:template>
<xsl:template match="@*">
<xsl:attribute name="{name()}" namespace=""><xsl:value-of select="."/></xsl:attribute>
</xsl:template>
</xsl:stylesheet>

Обратите внимание, что на элементы / атрибут, namespace="" очищает пространство имен Вместо этого вы также можете указать другое пространство имен.

С input.xml лайк

<?xml version="1.0"?>
<ns:abcd xmlns:ns="http://bla/bla">
<ns:defg attr="value">
<ns:hijk>
</ns:hijk>
</ns:defg>
</ns:abcd>

xsltproc xform.xsl input.xml печатает:

<abcd>
<defg attr="value">
<hijk>
</hijk>
</defg>
</abcd>
2

По вопросам рекламы [email protected]