【问题标题】:libxml: building a DOM tree from a xmlTextReaderPtr , handling namespaceslibxml:从 xmlTextReaderPtr 构建 DOM 树,处理命名空间
【发布时间】:2012-02-11 12:01:09
【问题描述】:

我正在尝试从xmlTextReaderPtr 构建DOM tree。在我的最终程序中,它将用于处理来自大型 XML 文件(如 I did in java)的带有 xslt 的小型 DOM 树。我找不到使用命名空间/前缀的正确方法(我应该如何创建元素和属性?)。这是一个非常基本的 C 代码:我正在从流中构建 DOM,然后转储 DOM。我应该如何修改我的代码来处理命名空间/前缀?非常感谢!

#include <stdio.h>
#include <libxml/parser.h>
#include <libxml/tree.h>
#include <libxml/xmlreader.h>


/* dump XML node */
static void print_element_names(xmlNode * a_node)
    {
        xmlNode *cur_node = NULL;

        for (cur_node = a_node; cur_node; cur_node = xmlNextElementSibling(cur_node))
        {
        if (cur_node->type == XML_ELEMENT_NODE) 
            {
            xmlAttrPtr attr;
                printf("node type: Element, name: %s", cur_node->name);
            if(cur_node->ns!=0 && cur_node->ns->href!=0) printf(" with namespace: %s", cur_node->ns->href);
            printf("\n");
            for(attr = cur_node->properties; NULL != attr; attr = attr->next)
                {
                xmlChar* v=xmlGetProp( cur_node,attr->name);
                printf(" @%s=%s ", attr->name,v);
                xmlFree(v);
                }

            }

        print_element_names(cur_node->children);
        }
    }


int main(int argc,char** argv)
    {
    LIBXML_TEST_VERSION;
    xmlTextReaderPtr reader;
    xmlDocPtr doc = NULL;
    xmlNodePtr current=NULL;
    xmlNsPtr ns=NULL;
    /* read from stdin */
    reader=xmlReaderForFd(fileno(stdin),0,"UTF-8",0);


    for(;;)
        {
        int nodeType;
        int ret = xmlTextReaderRead(reader);
        if(ret<=0) break;
        nodeType=xmlTextReaderNodeType(reader);

        switch(nodeType)
            {
            case XML_READER_TYPE_ELEMENT:
                {
                xmlNsPtr ns=0;
                xmlNodePtr node;
                if(doc==NULL)
                    {
                    doc=xmlNewDoc( BAD_CAST "1.0");
                    }
                if(xmlTextReaderConstNamespaceUri(reader)!=0)
                    {
                    /** how should I handle the attributes' namespaces & prefix here ? */
                    xmlNsPtr ns=xmlSearchNs(doc,current,xmlTextReaderConstNamespaceUri(reader));
                    node=xmlNewNode(ns, xmlTextReaderConstName(reader));
                    if(ns==0)
                        {
                        ns=xmlNewNs(node,
                            xmlTextReaderConstPrefix(reader),
                            xmlTextReaderConstNamespaceUri(reader)
                            );
                        }
                    }
                else
                    {
                    node=xmlNewNode(0, xmlTextReaderConstName(reader));
                    }

                if(current==NULL)
                    {
                    xmlDocSetRootElement(doc,node);
                    }
                else
                    {

                    xmlAddChild(current,node);
                    }

                current=node;

                if(xmlTextReaderIsEmptyElement(reader))
                     {
                     current= current->parent;
                     }


                if(xmlTextReaderHasAttributes(reader))
                     {
                     int i;
                     int n_att=xmlTextReaderAttributeCount(reader);
                     for(i=0;i< n_att;++i)
                     {
                     const xmlChar* k;
                     xmlChar* v;
                     xmlTextReaderMoveToAttributeNo(reader,i);
                     k = xmlTextReaderConstName(reader);
                     v = xmlTextReaderValue(reader);
                    /** how should I handle the attributes' namespaces & prefix here ? */
                     xmlNewProp(node,k, v);
                     xmlFree(v);
                     }
                     xmlTextReaderMoveToElement(reader);
                     }

                break;
                }
             case XML_READER_TYPE_END_ELEMENT:
                 {
                 current= current->parent;
                 break;
                 }
             case XML_READER_TYPE_SIGNIFICANT_WHITESPACE:
             case XML_READER_TYPE_TEXT:
                 {
                 const xmlChar* v = xmlTextReaderConstValue(reader);
                 xmlNodePtr node= xmlNewDocText(doc,v);
                 xmlAddChild(current,node);
                 break;
                 }
            default:
                {
                fprintf(stderr,"Ignoring node Type %d\n",nodeType);
                break;
                }
            }
        }
    if(doc!=NULL)
        {
        print_element_names(xmlDocGetRootElement(doc));
        xmlDocDump(stderr,doc);
        xmlFreeDoc(doc);
        }
    xmlFreeTextReader(reader);
    xmlCleanupParser();
    xmlMemoryDump();
    return 0;
    }

这是我的测试文件:

<?xml version="1.0"?>
<a xmlns="http://urn1.org" xmlns:ns1="http://urn2.org" ns1:test="ok">azdazd
    <b xmlns:ns2="http://urn3.org" xmlns:ns3="http://urn4.org" ns3:test="OK"/>
    azd
    <ns1:b test="ok"/>
    xaz
</a>

非常感谢,

【问题讨论】:

    标签: c xml namespaces stream libxml2


    【解决方案1】:

    好的,我发现了我的错误以及如何使用 API。代码如下:

    #include <stdio.h>
    #include <libxml/parser.h>
    #include <libxml/tree.h>
    #include <libxml/xmlreader.h>
    
    #define WHERE fprintf(stderr,"[DEBUG]line:%d\n",__LINE__)
    
    /* dump XML node */
    static void print_element_names(xmlNode * a_node)
        {
            xmlNode *cur_node = NULL;
    
            for (cur_node = a_node; cur_node; cur_node = xmlNextElementSibling(cur_node))
            {
            if (cur_node->type == XML_ELEMENT_NODE) 
                {
                xmlAttrPtr attr;
                printf("node type: Element, name: %s", cur_node->name);
                xmlNsPtr ns=cur_node->nsDef;
                while(ns!=0)
                    {
                    printf(" with namespace: %s %p\n", ns->href,ns->prefix);
                    ns=ns->next;
                    }
    
                printf("\n");
                for(attr = cur_node->properties; NULL != attr; attr = attr->next)
                    {
                    xmlChar* v=xmlGetProp( cur_node,attr->name);
    
            if(attr->ns!=0)
                {
                printf(" with namespace: %s %p\n", attr->ns->href,attr->ns->prefix);
    
                }
                    printf(" @%s=%s ", attr->name,v);
                    xmlFree(v);
                    }
            printf("\n");
                }
    
            print_element_names(cur_node->children);
            }
        }
    
    
    int main(int argc,char** argv)
        {
        LIBXML_TEST_VERSION;
        xmlTextReaderPtr reader;
        xmlDocPtr doc = NULL;
        xmlNodePtr current=NULL;
        /* read from stdin */
        reader=xmlReaderForFd(fileno(stdin),0,"UTF-8",0);
    
    
        for(;;)
            {
            int nodeType;
            int ret = xmlTextReaderRead(reader);
            if(ret<=0) break;
            nodeType=xmlTextReaderNodeType(reader);
    
            switch(nodeType)
                {
                case XML_READER_TYPE_ELEMENT:
                    {
                    xmlNsPtr ns=0;
                    xmlNodePtr node;
                    if(doc==NULL)
                        {
                        doc=xmlNewDoc( BAD_CAST "1.0");
                        }
                    if(xmlTextReaderConstNamespaceUri(reader)!=0)
                        {
                        xmlNsPtr ns=xmlSearchNs(doc,current,xmlTextReaderConstNamespaceUri(reader));
                        node=xmlNewNode(ns, xmlTextReaderConstName(reader));
                        if(ns==0)
                            {
                            WHERE;
                            ns=xmlNewNs(node,
                                xmlTextReaderConstNamespaceUri(reader),
                                xmlTextReaderConstPrefix(reader)
                                );
                            }
                        }
                    else
                        {
                        node=xmlNewNode(0, xmlTextReaderConstName(reader));
                        }
    
                    if(current==NULL)
                        {
                        xmlDocSetRootElement(doc,node);
                        }
                    else
                        {
    
                        xmlAddChild(current,node);
                        }
    
                    current=node;
    
    
    
    
                    if(xmlTextReaderHasAttributes(reader))
                         {
                         int i;
                         int n_att=xmlTextReaderAttributeCount(reader);
                         for(i=0;i< n_att;++i)
                         {
                         const xmlChar* k;
                         xmlChar* v;
                         xmlTextReaderMoveToAttributeNo(reader,i);
                         k = xmlTextReaderConstName(reader);
                         v = xmlTextReaderValue(reader);
                         if(xmlTextReaderConstNamespaceUri(reader)!=0)
                            {
                            if(!xmlStrEqual(xmlTextReaderConstNamespaceUri(reader),BAD_CAST "http://www.w3.org/2000/xmlns/"))
                            {
                        xmlNsPtr ns=xmlSearchNs(doc,current,xmlTextReaderConstNamespaceUri(reader));
                            if(ns==0)
                            {
                            ns=xmlNewNs(node,
                                xmlTextReaderConstNamespaceUri(reader),
                                xmlTextReaderConstPrefix(reader)
                                );
                            }
                        xmlNewNsProp(current,ns,
                            xmlTextReaderConstLocalName(reader)
                            ,
                            v);
                        }
                            }
                         else
                            {
                            xmlNewProp(current,k, v);
                            }
    
    
                         xmlFree(v);
                         }
                         xmlTextReaderMoveToElement(reader);
                         }
            if(xmlTextReaderIsEmptyElement(reader))
                         {
                         current= current->parent;
                         }
                    break;
                    }
                 case XML_READER_TYPE_END_ELEMENT:
                     {
                     current= current->parent;
                     break;
                     }
                 case XML_READER_TYPE_SIGNIFICANT_WHITESPACE:
                 case XML_READER_TYPE_TEXT:
                     {
                     const xmlChar* v = xmlTextReaderConstValue(reader);
                     xmlNodePtr node= xmlNewDocText(doc,v);
                     xmlAddChild(current,node);
                     break;
                     }
                default:
                    {
                    fprintf(stderr,"Ignoring node Type %d\n",nodeType);
                    break;
                    }
                }
            }
        if(doc!=NULL)
            {
            print_element_names(xmlDocGetRootElement(doc));
            xmlDocDump(stderr,doc);
            xmlFreeDoc(doc);
            }
        xmlFreeTextReader(reader);
        xmlCleanupParser();
        xmlMemoryDump();
        return 0;
        }
    

    【讨论】:

      猜你喜欢
      • 2012-09-07
      • 1970-01-01
      • 1970-01-01
      • 2011-02-28
      • 2014-10-14
      • 1970-01-01
      • 2014-01-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多