libxml: построение дерева DOM из xmlTextReaderPtr, обработка пространств имен - PullRequest
2 голосов
/ 16 января 2012

Я пытаюсь построить дерево DOM из xmlTextReaderPtr . В моей последней программе она будет использоваться для обработки небольшого дерева DOM с помощью xslt из большого XML-файла, такого как , который я сделал в java . Я не могу найти правильный способ работы с пространствами имен / префиксами (как мне создавать элементы и атрибуты?). Вот очень простой 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>

Большое спасибо,

1 Ответ

2 голосов
/ 17 января 2012

Хорошо, я нашел свои ошибки и как использовать 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;
    }
...