代码之家  ›  专栏  ›  技术社区  ›  Aman Aggarwal Charlie

有没有一种方法可以使用C++/Boost或其他库从xml标记中删除名称空间

  •  1
  • Aman Aggarwal Charlie  · 技术社区  · 10 年前

    有办法进去吗 C++ ,使用 丁尼克毫升 , TinyX路径 ,这样 一串 包含:

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

    转换为

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

    编辑:

    我在用Tinyxml和Tinyxpath。

    我的工作流程是:

    a) 使用TinyXML创建dom树

    b) 将dom树传递给Tinyxpath评估

    为了添加命名空间删除,我使用了以下函数:

    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);
        }
    }
    

    因此工作流更改为:

    a) 使用TinyXML创建dom树

    b) 使用从domtree中删除命名空间 RemoveAllNamespaces(domtree.Root() )

    c) 将修改后的dom树传递给Tinyxpath评估

    2 回复  |  直到 10 年前
        1
  •  2
  •   sehe    10 年前

    我将在这里使用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
  •  1
  •   sehe    10 年前

    好的,针对编辑后的问题,请注意以下几点:

    • 这实际上不处理名称空间(请考虑 xmlns="http://blabla.com/uri" 样式默认命名空间),但这实际上是TinyXml限制(eek):

      此外,TinyXML没有处理XML名称空间的工具。限定的元素或属性名称保留其前缀,因为TinyXML不努力将前缀与名称空间匹配。

    • 它不处理属性(也可以限定)

    下面是我要做的一件事;dirty(假设您已经在使用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);
        }
    }
    

    在…上 my MSVC test 它会打印

    <?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>