API синтаксического анализа miniXML - PullRequest
3 голосов
/ 21 марта 2012

Я пытаюсь разобрать следующий XML-файл:

<root>Root
    <pai>Pai_1
        <filho>Pai1,Filho1</filho>
        <filho>Pai1,Filho2</filho>
    </pai>
    <pai>Pai_2
        <filho>Pai2,Filho1</filho>
        <filho>Pai2,Filho2</filho>
    </pai>
</root>

Я использую следующий код C:

//... open file
xml_tree = mxmlLoadFile(NULL, fp, MXML_TEXT_CALLBACK);

node = xml_tree;
printf("%s\n", mxmlGetText(node, NULL));
// here the return is: Root
// I expected: Root, OK

node = xml_tree->child;
printf("%s\n", mxmlGetText(node, NULL));
// here the return is: Root
// I expected: Pai_1, not OK

node = mxmlGetFirstChild(xml_tree);
printf("%s\n", mxmlGetText(node, NULL));
// here the return is: Root
// I expected: Pai_1, not OK

node = mxmlFindElement(xml_tree, xml_tree, "pai", NULL, NULL, MXML_DESCEND);
printf("%s\n", mxmlGetText(node, NULL));
// here the return is: Pai_1
// I expected: Pai_1, OK

node = mxmlGetNextSibling(node);
printf("%s\n", mxmlGetText(node, NULL));
// here the return is: (NULL)
// I expected: Pai_2, not OK

Как получить доступ к дочернему элементу root?Где моя концепция доступа неверна?

Спасибо.


РЕДАКТИРОВАТЬ после ответа @RutgersMike

Я расширяю ваш цикл while, чтобы попытаться понять концепцию minixml:

root = mxmlLoadFile(NULL,fp,MXML_TEXT_CALLBACK);
node = root;

printf("------- Root\n");
fprintf(stdout,"Element = %s\n",mxmlGetElement(node));
fprintf(stdout,"  Value = %s\n",mxmlGetText(node,0));
printf("\n");

printf("------- First child of Root\n");
node = mxmlGetFirstChild(node);
fprintf(stdout,"Element = %s\n",mxmlGetElement(node));
fprintf(stdout,"  Value = %s\n",mxmlGetText(node,0));
printf("\n");

printf("------- Sibling 1 of First child of Root\n");
node = mxmlGetNextSibling(node);
fprintf(stdout,"Element = %s\n",mxmlGetElement(node));
fprintf(stdout,"  Value = %s\n",mxmlGetText(node,0));
printf("\n");

printf("------- Sibling 2 of First child of Root\n");
node = mxmlGetNextSibling(node);
fprintf(stdout,"Element = %s\n",mxmlGetElement(node));
fprintf(stdout,"  Value = %s\n",mxmlGetText(node,0));
printf("\n");

printf("------- Sibling 3 of First child of Root\n");
node = mxmlGetNextSibling(node);
fprintf(stdout,"Element = %s\n",mxmlGetElement(node));
fprintf(stdout,"  Value = %s\n",mxmlGetText(node,0));
printf("\n");

printf("------- Sibling 4 of First child of Root\n");
node = mxmlGetNextSibling(node);
fprintf(stdout,"Element = %s\n",mxmlGetElement(node));
fprintf(stdout,"  Value = %s\n",mxmlGetText(node,0));
printf("\n");

В результате это было:

------- Root
Element = root
  Value = Root

------- First child of Root
Element = (null)
  Value = Root

------- Sibling 1 of First child of Root
Element = (null)
  Value = 

------- Sibling 2 of First child of Root
Element = pai
  Value = Pai_1

------- Sibling 3 of First child of Root
Element = (null)
  Value = 

------- Sibling 4 of First child of Root
Element = pai
  Value = Pai_2

Я думаю, что это понятие навигации между ребенком и родителем немного странно.Почему между братьями и сестрами есть (нулевые) значения?

Я думаю вернуться к ezxml.

Спасибо

Ответы [ 2 ]

7 голосов
/ 15 июля 2012

Просто начав играть с min-xml, и хотя я был крайне разочарован отсутствием хороших примеров, я позаимствовал и улучшил, чтобы дать достойный, но не идеальный пример чтения файла XML и просмотра всех частей.Он показывает имя тега, атрибуты и текстовые значения между тегами.Не уверен, как определить конечный тег.Убедитесь, что стандартный тег XML находится в верхней части файла XML.Включите файлы stdio, stdlib, string .h.

#include "mxml.h"

int main (int argc, char **argv ) {

         FILE *fp  = NULL;

         int k = 0;

         mxml_node_t * tree = NULL;
         mxml_node_t * node  = NULL;

         if (argc < 2){
             perror("Argument Required XML File ");
             exit(1);
         }
         fp = fopen (argv[1], "r");
         if (fp ){
             tree = mxmlLoadFile (NULL , fp , MXML_OPAQUE_CALLBACK);
         }else {
             perror("Could Not Open the File Provided");
             exit(1);
         }
         if (tree){
                 for (node = mxmlFindElement(tree, tree,NULL,NULL, NULL,MXML_DESCEND);
                         node != NULL;
                         node=mxmlWalkNext (node, NULL, MXML_DESCEND)
                         //node = mxmlFindElement(node, tree, NULL,NULL,NULL,MXML_DESCEND)
                 ){
                         if (node->type  == MXML_ELEMENT) {
                             printf("MXML_ELEMENT Node <%s>:%d \n", node->value.element.name, node->value.element.num_attrs);
                             for (k = 0; k < node->value.element.num_attrs; k++){
                                 if (node->value.element.attrs ){
                                     printf ("Attribute Name :: %s \n", node->value.element.attrs[k].name);
                                     printf ("Attribute Value:: %s \n", node->value.element.attrs[k].value);
                                 }
                                 //if (!strncmp(node->value.element.name , "display-name", 12 )){
                                 //    printf(" String %s \n", (char*) node->child->value.text.string);
                                 //}
                             }
                         }
                         else if (node->type == MXML_REAL){
                             printf("MXML_REAL Node is %s \n", node->value.element.name);
                         }
                         else if(node->type == MXML_OPAQUE){
                             printf("MXML_OPAQUE Node is %s \n", node->value.element.name);
                         }
                         else if(node->type == MXML_INTEGER){
                             printf("MXML_INTEGER Node is %s \n", node->value.element.name);
                         }
                         else if(node->type == MXML_TEXT){
                             printf("MXML_TEXT Node is %s \n", node->value.element.name);
                         }
                         else if(node->type == MXML_IGNORE){
                             printf("MXML_IGNORE Node is %s \n", node->value.element.name);
                         }
                         else if(node->type == MXML_CUSTOM){
                             printf("MXML_IGNORE Node is %s \n", node->value.element.name);
                         }
                         else {
                             printf("Type Default Node is %s \n", node->value.element.name);
                         }
                 }
         }
         if (tree){
            mxmlDelete(tree);
         }
         if (fp){
            fclose(fp);
         }
         return 0;
}
5 голосов
/ 21 марта 2012

Похоже, вы хотите использовать описанные здесь итерационные функции (http://www.minixml.org/mxml.html#3_7) для получения дочерних узлов.

РЕДАКТИРОВАТЬ: я написал это, чтобы перебрать первый дочерний узел, и он отлично работает, использовал mxmlGetFirstChild и mxmlGetNextSibling:

<!-- language: c -->
mxml_node_t* node = mxmlLoadFile(NULL,f,MXML_TEXT_CALLBACK);
while ( node != NULL )
{
   switch ( mxmlGetType(node) )
   {
   case MXML_ELEMENT:
   {
      fprintf(stdout,"Element = %s\n",mxmlGetElement(node));
   }
   break;
   case MXML_TEXT:
   {
      fprintf(stdout,"  Value = %s\n",mxmlGetText(node,0));
   }
   break;
   default:
   {
   }
   break;
   }
   mxml_node_t* next = mxmlGetFirstChild(node);
   if ( next != NULL )
   {
      node = next;
   }
   else
   {
      next = mxmlGetNextSibling(node);
      if ( next != NULL )
      {
         node = next;
      }
      else
      {
         node = next;
         fprintf(stdout,"Done\n");
      }
   }
}

Производит продукцию:

Element = root
Value = Root
Value = 
Element = pai
Value = Pai_1
Value = 
Element = filho
Value = Pai1,Filho1

Я предполагаю, что вы можете использовать одну из функций getParent, чтобы выполнить итерацию обратно, или сохранить последний узел перед погружением в дочерний узел, используя стек указателей узлов, если вы хотите выполнить итерацию по всему файлу. Обратите внимание, что я обрабатываю / печатаю данные только для двух типов узлов - вы захотите поэкспериментировать, чтобы увидеть, что содержат другие типы узлов, если вам также нужна эта информация.

** БОЛЬШЕ РЕДАКТИРОВАТЬ после редактирования **

На днях я предложил кому-то еще попробовать libxml2 (http://xmlsoft.org/examples/index.html#xmlReader) - проверить эту ссылку. Пример xmlReader показывает использование. Невероятно легко создать читатель и выполнить итерации по узлам - когда нажмите на каждый узел, просто проверьте его тип, чтобы убедиться, что он вам нужен (обычно ELEMENT, ATTRIBUTE, TEXT и END_ELEMENT), а затем вытащите либо имя, либо значение. Мне это очень нравится лучше, чем mxml.

...