gwenhywfar  5.1.2
xml2db.c
Go to the documentation of this file.
1 /***************************************************************************
2  begin : Sun Dec 16 2018
3  copyright : (C) 2018 by Martin Preuss
4  email : martin@libchipcard.de
5 
6  ***************************************************************************
7  * *
8  * This library is free software; you can redistribute it and/or *
9  * modify it under the terms of the GNU Lesser General Public *
10  * License as published by the Free Software Foundation; either *
11  * version 2.1 of the License, or (at your option) any later version. *
12  * *
13  * This library is distributed in the hope that it will be useful, *
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
16  * Lesser General Public License for more details. *
17  * *
18  * You should have received a copy of the GNU Lesser General Public *
19  * License along with this library; if not, write to the Free Software *
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
21  * MA 02111-1307 USA *
22  * *
23  ***************************************************************************/
24 
25 
26 #ifdef HAVE_CONFIG_H
27 # include <config.h>
28 #endif
29 
30 
31 
32 #include "xml2db_p.h"
33 
34 #include <gwenhywfar/debug.h>
35 #include <gwenhywfar/text.h>
36 #include <gwenhywfar/gwendate.h>
37 
38 
39 #include <ctype.h>
40 
41 
42 
43 GWEN_XML2DB_CONTEXT *GWEN_Xml2Db_Context_new(GWEN_XMLNODE *documentRoot, GWEN_DB_NODE *dbRoot)
44 {
45  GWEN_XML2DB_CONTEXT *ctx;
46 
47  GWEN_NEW_OBJECT(GWEN_XML2DB_CONTEXT, ctx);
48  assert(ctx);
49 
50  ctx->docRoot=documentRoot;
51  ctx->xmlNodeStack=GWEN_XMLNode_List2_new();
52  ctx->dbRoot=dbRoot;
53  ctx->tempDbRoot=GWEN_DB_Group_new("dbTempRoot");
54 
55  ctx->currentDbGroup=ctx->dbRoot;
56  ctx->currentTempDbGroup=ctx->tempDbRoot;
57  ctx->currentDocNode=documentRoot;
58 
59  return ctx;
60 }
61 
62 
63 
64 void GWEN_Xml2Db_Context_free(GWEN_XML2DB_CONTEXT *ctx)
65 {
66  if (ctx) {
67  GWEN_XMLNode_List2_free(ctx->xmlNodeStack);
68  ctx->xmlNodeStack=NULL;
69 
70  GWEN_DB_Group_free(ctx->tempDbRoot);
71  GWEN_FREE_OBJECT(ctx);
72  }
73 }
74 
75 
76 
77 void GWEN_Xml2Db_Context_EnterDocNode(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
78 {
79  assert(ctx);
80  assert(xmlNode);
81 
82  GWEN_XMLNode_List2_PushBack(ctx->xmlNodeStack, ctx->currentDocNode);
83  ctx->currentDocNode=xmlNode;
84 }
85 
86 
87 
88 void GWEN_Xml2Db_Context_LeaveDocNode(GWEN_XML2DB_CONTEXT *ctx)
89 {
90  GWEN_XMLNODE *xmlNode;
91 
92  assert(ctx);
93 
94  xmlNode=GWEN_XMLNode_List2_GetBack(ctx->xmlNodeStack);
95  if (xmlNode==NULL) {
96  DBG_ERROR(GWEN_LOGDOMAIN, "Nothing on stack");
97  assert(xmlNode);
98  }
99  ctx->currentDocNode=xmlNode;
100  GWEN_XMLNode_List2_PopBack(ctx->xmlNodeStack);
101 }
102 
103 
104 
105 
106 
107 
108 const char *GWEN_Xml2Db_GetCharValueByPath(GWEN_XMLNODE *xmlNode, const char *path, const char *defValue)
109 {
110  const char *s;
111 
112  s=strchr(path, '@');
113  if (s) {
114  int idx;
115  char *cpyOfPath;
116  char *property;
117  GWEN_XMLNODE *n;
118 
119 
120  idx=s-path;
121  cpyOfPath=strdup(path);
122  assert(cpyOfPath);
123  cpyOfPath[idx]=0;
124  property=cpyOfPath+idx+1;
125 
126  if (*cpyOfPath) {
128  }
129  else
130  n=xmlNode;
131 
132  if (n) {
133  const char *result;
134 
135  result=GWEN_XMLNode_GetProperty(n, property, defValue);
136  DBG_INFO(GWEN_LOGDOMAIN, "Got XML property: %s = %s (%s)", property, result, path);
137  free(cpyOfPath);
138  return result;
139  }
140  free(cpyOfPath);
141  return defValue;
142  }
143  else
144  return GWEN_XMLNode_GetCharValueByPath(xmlNode, path, defValue);
145 }
146 
147 
148 /* TODO: optimize later */
149 int GWEN_Xml2Db_ConvertAndSetCharValue(GWEN_UNUSED GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode,
150  GWEN_DB_NODE *dbCurrent,
151  const char *value)
152 {
153  if (value && *value) {
154  const char *name;
155  const char *typ;
156  const char *mode;
157  int doTrim=0;
158  GWEN_BUFFER *vbuf;
159  GWEN_BUFFER *resultBuf;
160 
161  doTrim=GWEN_XMLNode_GetIntProperty(xmlNode, "trim", 0);
162  vbuf=GWEN_Buffer_new(0, 256, 0, 1);
163  resultBuf=GWEN_Buffer_new(0, 256, 0, 1);
164 
165  name=GWEN_XMLNode_GetProperty(xmlNode, "name", NULL);
166  if (!(name && *name)) {
167  DBG_ERROR(GWEN_LOGDOMAIN, "Missing or empty name in \"SetCharValue\"");
168  GWEN_Buffer_free(resultBuf);
169  GWEN_Buffer_free(vbuf);
170  return GWEN_ERROR_INVALID;
171  }
172 
173  typ=GWEN_XMLNode_GetProperty(xmlNode, "type", "string");
174  if (!(typ && *typ)) {
175  DBG_ERROR(GWEN_LOGDOMAIN, "Empty type in \"SetCharValue\"");
176  GWEN_Buffer_free(resultBuf);
177  GWEN_Buffer_free(vbuf);
178  return GWEN_ERROR_INVALID;
179  }
180 
181  mode=GWEN_XMLNode_GetProperty(xmlNode, "mode", "add");
182 
183  if (strcasecmp(typ, "string")==0) {
184  GWEN_Buffer_AppendString(vbuf, value);
185  if (doTrim)
187  }
188  else if (strcasecmp(typ, "date")==0) {
189  const char *tmpl;
190  GWEN_DATE *dt=NULL;
191 
192  tmpl=GWEN_XMLNode_GetProperty(xmlNode, "template", "YYYYMMDD");
193  if (!(tmpl && *tmpl)) {
194  DBG_ERROR(GWEN_LOGDOMAIN, "Empty template in \"SetCharValue\"");
195  GWEN_Buffer_free(resultBuf);
196  GWEN_Buffer_free(vbuf);
197  return GWEN_ERROR_INVALID;
198  }
199 
200  dt=GWEN_Date_fromStringWithTemplate(value, tmpl);
201  if (dt) {
203  GWEN_Date_free(dt);
204  }
205  }
206 
207  if (strcasecmp(mode, "add")==0) {
208  /* just exchange the buffer */
209  GWEN_Buffer_free(resultBuf);
210  resultBuf=vbuf;
211  vbuf=NULL;
212  }
213  else if (strcasecmp(mode, "append")==0) {
214  const char *s;
215 
216  s=GWEN_DB_GetCharValue(dbCurrent, name, 0, NULL);
217  if (s && *s) {
218  const char *delimiter;
219 
220  /* write previous data into resultBuffer */
221  GWEN_Buffer_AppendString(resultBuf, s);
222 
223  /* possibly write delimiter into resultBuffer */
224  delimiter=GWEN_XMLNode_GetProperty(xmlNode, "delimiter", NULL);
225  if (delimiter && *delimiter) {
226  if (strcasecmp(delimiter, "\\n")==0)
227  GWEN_Buffer_AppendByte(resultBuf, '\n');
228  else if (strcasecmp(delimiter, "\\t")==0)
229  GWEN_Buffer_AppendByte(resultBuf, '\t');
230  else
231  GWEN_Buffer_AppendString(resultBuf, delimiter);
232  }
233  } /* if previous value */
234  /* write value into resultBuffer */
236 
237  GWEN_DB_DeleteVar(dbCurrent, name);
238  }
239  else if (strcasecmp(mode, "replace")==0) {
240  /* just exchange the buffer */
241  GWEN_Buffer_free(resultBuf);
242  resultBuf=vbuf;
243  vbuf=NULL;
244  GWEN_DB_DeleteVar(dbCurrent, name);
245  }
246 
247  DBG_INFO(GWEN_LOGDOMAIN, "Setting value: %s = %s", name, GWEN_Buffer_GetStart(resultBuf));
248 
250  GWEN_Buffer_free(resultBuf);
251  GWEN_Buffer_free(vbuf);
252  }
253  return 0;
254 }
255 
256 
257 
258 
259 
260 
261 
262 int GWEN_Xml2Db_Handle_XmlEnter(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
263 {
264  const char *path;
265  GWEN_XMLNODE *n;
266  int rv;
267 
268  path=GWEN_XMLNode_GetProperty(xmlNode, "path", NULL);
269  if (path==NULL) {
270  DBG_ERROR(GWEN_LOGDOMAIN, "Missing path in \"EnterPath\"");
271  return GWEN_ERROR_INVALID;
272  }
273 
274  n=GWEN_XMLNode_GetNodeByXPath(ctx->currentDocNode, path, GWEN_PATH_FLAGS_PATHMUSTEXIST);
275  if (n==NULL) {
276  DBG_ERROR(GWEN_LOGDOMAIN, "Path \"%s\" does not exist", path);
277  return GWEN_ERROR_INVALID;
278  }
279 
280  /* enter given document node */
282 
283  rv=GWEN_Xml2Db_HandleChildren(ctx, xmlNode);
284  if (rv<0) {
285  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
286  return rv;
287  }
288 
289  /* leave given document node, re-select previously active one, thus restoring status from the beginning */
291  return 0;
292 }
293 
294 
295 
296 int GWEN_Xml2Db_Handle_XmlForEvery(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
297 {
298  const char *path;
299  GWEN_XMLNODE *n;
300  int rv;
301 
302  path=GWEN_XMLNode_GetProperty(xmlNode, "name", NULL);
303  if (path==NULL) {
304  DBG_ERROR(GWEN_LOGDOMAIN, "Missing name in \"ForEvery\"");
305  return GWEN_ERROR_INVALID;
306  }
307 
308  n=GWEN_XMLNode_FindFirstTag(ctx->currentDocNode, path, NULL, NULL);
309  if (n==NULL) {
310  DBG_ERROR(GWEN_LOGDOMAIN, "Path \"%s\" not found", path);
311  /* GWEN_XMLNode_Dump(ctx->currentDocNode, 2); */
312  }
313  while (n) {
314 
315  /* enter given document node */
317 
318  /* handle all children of this parser XML node with the current document node */
319  rv=GWEN_Xml2Db_HandleChildren(ctx, xmlNode);
320 
321  /* leave given document node, re-select previously active one, thus restoring status from the beginning */
323 
324  if (rv<0) {
325  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
326  return rv;
327  }
328 
329  n=GWEN_XMLNode_FindNextTag(n, path, NULL, NULL);
330  }
331 
332  return 0;
333 }
334 
335 
336 
337 int GWEN_Xml2Db_Handle_DbCreateAndEnterGroup(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
338 {
339  const char *name;
340  GWEN_DB_NODE *dbLast;
341  int rv;
342 
343  name=GWEN_XMLNode_GetProperty(xmlNode, "name", NULL);
344  if (!(name && *name)) {
345  DBG_ERROR(GWEN_LOGDOMAIN, "Missing or empty name in \"CreateAnEnterDbGroup\"");
346  return GWEN_ERROR_INVALID;
347  }
348 
349  /* push group */
350  dbLast=ctx->currentDbGroup;
351 
352  /* create group */
353  ctx->currentDbGroup=GWEN_DB_GetGroup(dbLast, GWEN_PATH_FLAGS_CREATE_GROUP, name);
354 
355  /* handle children (nothing special here) */
356  rv=GWEN_Xml2Db_HandleChildren(ctx, xmlNode);
357 
358  /* pop group */
359  ctx->currentDbGroup=dbLast;
360 
361  if (rv<0) {
362  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
363  return rv;
364  }
365 
366  return 0;
367 }
368 
369 
370 
371 int GWEN_Xml2Db_Handle_DbCreateAndEnterTempGroup(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
372 {
373  const char *name;
374  GWEN_DB_NODE *dbLast;
375  int rv;
376 
377  name=GWEN_XMLNode_GetProperty(xmlNode, "name", NULL);
378  if (!(name && *name)) {
379  DBG_ERROR(GWEN_LOGDOMAIN, "Missing or empty name in \"CreateAnEnterTempDbGroup\"");
380  return GWEN_ERROR_INVALID;
381  }
382 
383  /* push group */
384  dbLast=ctx->currentTempDbGroup;
385 
386  /* create group */
387  ctx->currentTempDbGroup=GWEN_DB_GetGroup(dbLast, GWEN_PATH_FLAGS_CREATE_GROUP, name);
388  assert(ctx->currentTempDbGroup);
389 
390  /* handle children (nothing special here) */
391  rv=GWEN_Xml2Db_HandleChildren(ctx, xmlNode);
392 
393  /* delete temp group */
394  GWEN_DB_UnlinkGroup(ctx->currentTempDbGroup);
395  GWEN_DB_Group_free(ctx->currentTempDbGroup);
396 
397  /* pop group */
398  ctx->currentTempDbGroup=dbLast;
399 
400  if (rv<0) {
401  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
402  return rv;
403  }
404 
405  return 0;
406 }
407 
408 
409 
410 int GWEN_Xml2Db_Handle_DbSetCharValue_internal(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode,
411  GWEN_DB_NODE *dbCurrent)
412 {
413  const char *name;
414  const char *value;
415 
416  name=GWEN_XMLNode_GetProperty(xmlNode, "name", NULL);
417  if (!(name && *name)) {
418  DBG_ERROR(GWEN_LOGDOMAIN, "Missing or empty name in \"SetCharValue\"");
419  return GWEN_ERROR_INVALID;
420  }
421 
422  value=GWEN_XMLNode_GetProperty(xmlNode, "value", NULL);
423  if (value) {
424  GWEN_BUFFER *dbuf;
425  int rv;
426 
427  dbuf=GWEN_Buffer_new(0, 256, 0, 1);
428  rv=GWEN_DB_ReplaceVars(ctx->currentTempDbGroup, value, dbuf);
429  if (rv<0) {
430  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
431  GWEN_Buffer_free(dbuf);
432  return rv;
433  }
434  GWEN_Xml2Db_ConvertAndSetCharValue(ctx, xmlNode, dbCurrent, GWEN_Buffer_GetStart(dbuf));
435  GWEN_Buffer_free(dbuf);
436  }
437  else {
438  const char *path;
439 
440  path=GWEN_XMLNode_GetProperty(xmlNode, "path", NULL);
441  if (!(path && *path)) {
442  DBG_ERROR(GWEN_LOGDOMAIN, "Missing or empty path in \"SetCharValue\"");
443  return GWEN_ERROR_INVALID;
444  }
445 
446  value=GWEN_Xml2Db_GetCharValueByPath(ctx->currentDocNode, path, NULL);
447  if (value && *value) {
448  GWEN_Xml2Db_ConvertAndSetCharValue(ctx, xmlNode, dbCurrent, value);
449  }
450  else {
451  GWEN_BUFFER *tbuf;
452 
453  tbuf=GWEN_Buffer_new(0, 256, 0, 1);
454 
455  GWEN_XMLNode_GetXPath(NULL, ctx->currentDocNode, tbuf);
456 
457  DBG_ERROR(GWEN_LOGDOMAIN, "No value in path \"%s\" (%s)", path, GWEN_Buffer_GetStart(tbuf));
458  GWEN_Buffer_free(tbuf);
459 
460  /* GWEN_XMLNode_Dump(ctx->currentDocNode, 2); */
461  }
462  }
463 
464  return 0;
465 }
466 
467 
468 
469 int GWEN_Xml2Db_Handle_DbSetCharValue(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
470 {
471  return GWEN_Xml2Db_Handle_DbSetCharValue_internal(ctx, xmlNode, ctx->currentDbGroup);
472 }
473 
474 
475 
476 int GWEN_Xml2Db_Handle_DbSetTempCharValue(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
477 {
478  return GWEN_Xml2Db_Handle_DbSetCharValue_internal(ctx, xmlNode, ctx->currentTempDbGroup);
479 }
480 
481 
482 
483 int GWEN_Xml2Db_Handle_XmlIfCharDataMatches(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
484 {
485  const char *pattern;
486  const char *path;
487  const char *value;
488 
489  path=GWEN_XMLNode_GetProperty(xmlNode, "path", NULL);
490  if (!(path && *path)) {
491  DBG_ERROR(GWEN_LOGDOMAIN, "Missing or empty path in \"IfCharDataMatches\"");
492  return GWEN_ERROR_INVALID;
493  }
494 
495  pattern=GWEN_XMLNode_GetProperty(xmlNode, "pattern", NULL);
496  if (!(pattern && *pattern)) {
497  DBG_ERROR(GWEN_LOGDOMAIN, "Missing or empty pattern in \"IfCharDataMatches\"");
498  return GWEN_ERROR_INVALID;
499  }
500 
501  value=GWEN_Xml2Db_GetCharValueByPath(ctx->currentDocNode, path, NULL);
502  if (value) {
503  if (-1!=GWEN_Text_ComparePattern(value, pattern, 0)) {
504  int rv;
505 
506  /* pattern matches, handle children */
507  rv=GWEN_Xml2Db_HandleChildren(ctx, xmlNode);
508  if (rv<0) {
509  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
510  return rv;
511  }
512  }
513  }
514 
515  return 0;
516 }
517 
518 
519 
520 int GWEN_Xml2Db_Handle_XmlIfNotCharDataMatches(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
521 {
522  const char *pattern;
523  const char *path;
524  const char *value;
525 
526  path=GWEN_XMLNode_GetProperty(xmlNode, "path", NULL);
527  if (!(path && *path)) {
528  DBG_ERROR(GWEN_LOGDOMAIN, "Missing or empty path in \"IfNotCharDataMatches\"");
529  return GWEN_ERROR_INVALID;
530  }
531 
532  pattern=GWEN_XMLNode_GetProperty(xmlNode, "pattern", NULL);
533  if (!(pattern && *pattern)) {
534  DBG_ERROR(GWEN_LOGDOMAIN, "Missing or empty pattern in \"IfNotCharDataMatches\"");
535  return GWEN_ERROR_INVALID;
536  }
537 
538  value=GWEN_Xml2Db_GetCharValueByPath(ctx->currentDocNode, path, NULL);
539  if (value) {
540  if (-1==GWEN_Text_ComparePattern(value, pattern, 0)) {
541  int rv;
542 
543  /* pattern doesnt match, handle children */
544  rv=GWEN_Xml2Db_HandleChildren(ctx, xmlNode);
545  if (rv<0) {
546  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
547  return rv;
548  }
549  }
550  }
551 
552  return 0;
553 }
554 
555 
556 
557 int GWEN_Xml2Db_Handle_XmlIfHasCharData(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
558 {
559  const char *path;
560  const char *value;
561 
562  path=GWEN_XMLNode_GetProperty(xmlNode, "path", NULL);
563  if (!(path && *path)) {
564  DBG_ERROR(GWEN_LOGDOMAIN, "Missing or empty path in \"IfCharDataMatches\"");
565  return GWEN_ERROR_INVALID;
566  }
567 
568  value=GWEN_Xml2Db_GetCharValueByPath(ctx->currentDocNode, path, NULL);
569  if (value && *value) {
570  int rv;
571 
572  /* there is a value, handle children */
573  rv=GWEN_Xml2Db_HandleChildren(ctx, xmlNode);
574  if (rv<0) {
575  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
576  return rv;
577  }
578  }
579  else {
580  DBG_INFO(GWEN_LOGDOMAIN, "No value for path \"%s\"", path);
581  }
582 
583  return 0;
584 }
585 
586 
587 
588 int GWEN_Xml2Db_Handle_XmlIfNotHasCharData(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
589 {
590  const char *path;
591  const char *value;
592 
593  path=GWEN_XMLNode_GetProperty(xmlNode, "path", NULL);
594  if (!(path && *path)) {
595  DBG_ERROR(GWEN_LOGDOMAIN, "Missing or empty path in \"IfNotCharDataMatches\"");
596  return GWEN_ERROR_INVALID;
597  }
598 
599  value=GWEN_Xml2Db_GetCharValueByPath(ctx->currentDocNode, path, NULL);
600  if (!(value && *value)) {
601  int rv;
602 
603  /* there is a value, handle children */
604  rv=GWEN_Xml2Db_HandleChildren(ctx, xmlNode);
605  if (rv<0) {
606  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
607  return rv;
608  }
609  }
610 
611  return 0;
612 }
613 
614 
615 
616 int GWEN_Xml2Db_Handle_XmlIfPathExists(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
617 {
618  const char *path;
619 
620  path=GWEN_XMLNode_GetProperty(xmlNode, "path", NULL);
621  if (!(path && *path)) {
622  DBG_ERROR(GWEN_LOGDOMAIN, "Missing or empty path in \"IfPathExists\"");
623  return GWEN_ERROR_INVALID;
624  }
625 
626  if (GWEN_XMLNode_GetNodeByXPath(ctx->currentDocNode, path, GWEN_PATH_FLAGS_PATHMUSTEXIST)) {
627  int rv;
628 
629  /* path exists, handle children */
630  rv=GWEN_Xml2Db_HandleChildren(ctx, xmlNode);
631  if (rv<0) {
632  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
633  return rv;
634  }
635  }
636  else {
637  DBG_INFO(GWEN_LOGDOMAIN, "Path \"%s\" does not exist", path);
638  }
639 
640  return 0;
641 }
642 
643 
644 
645 int GWEN_Xml2Db_Handle_XmlIfNotPathExists(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
646 {
647  const char *path;
648 
649  path=GWEN_XMLNode_GetProperty(xmlNode, "path", NULL);
650  if (!(path && *path)) {
651  DBG_ERROR(GWEN_LOGDOMAIN, "Missing or empty path in \"IfNotPathExists\"");
652  return GWEN_ERROR_INVALID;
653  }
654 
655  if (NULL==GWEN_XMLNode_GetNodeByXPath(ctx->currentDocNode, path, GWEN_PATH_FLAGS_PATHMUSTEXIST)) {
656  int rv;
657 
658  /* path does not exist, handle children */
659  rv=GWEN_Xml2Db_HandleChildren(ctx, xmlNode);
660  if (rv<0) {
661  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
662  return rv;
663  }
664  }
665  else {
666  DBG_INFO(GWEN_LOGDOMAIN, "Path \"%s\" exists", path);
667  }
668 
669  return 0;
670 }
671 
672 
673 
674 
675 int GWEN_Xml2Db_HandleChildren(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
676 {
677  GWEN_XMLNODE *n;
678 
679  n=GWEN_XMLNode_GetFirstTag(xmlNode);
680  while (n) {
681  const char *name;
682 
683  name=GWEN_XMLNode_GetData(n);
684  if (name && *name) {
685  int rv;
686 
687  DBG_INFO(GWEN_LOGDOMAIN, "Handling element \"%s\"", name);
688  if (strcasecmp(name, "XmlEnter")==0)
689  rv=GWEN_Xml2Db_Handle_XmlEnter(ctx, n);
690  else if (strcasecmp(name, "XmlForEvery")==0)
692  else if (strcasecmp(name, "DbCreateAndEnterGroup")==0)
694  else if (strcasecmp(name, "DbCreateAndEnterTempGroup")==0)
696  else if (strcasecmp(name, "DbSetCharValue")==0)
698  else if (strcasecmp(name, "DbSetTempCharValue")==0)
700  else if (strcasecmp(name, "XmlIfCharDataMatches")==0)
702  else if (strcasecmp(name, "XmlIfNotCharDataMatches")==0)
704  else if (strcasecmp(name, "XmlIfHasCharData")==0)
706  else if (strcasecmp(name, "XmlIfNotHasCharData")==0)
708  else if (strcasecmp(name, "XmlIfPathExists")==0)
710  else if (strcasecmp(name, "XmlIfNotPathExists")==0)
712  else {
713  DBG_ERROR(GWEN_LOGDOMAIN, "Unknown element \"%s\", aborting", name);
714  return GWEN_ERROR_INVALID;
715  }
716  if (rv<0) {
717  DBG_ERROR(GWEN_LOGDOMAIN, "Error in element \"%s\", aborting", name);
718  return rv;
719  }
720  }
721 
723  }
724 
725  return 0;
726 }
727 
728 
729 
730 
731 int GWEN_Xml2Db(GWEN_XMLNODE *xmlNodeDocument,
732  GWEN_XMLNODE *xmlNodeSchema,
733  GWEN_DB_NODE *dbDestination)
734 {
735  GWEN_XML2DB_CONTEXT *ctx;
736  int rv;
737 
738  ctx=GWEN_Xml2Db_Context_new(xmlNodeDocument, dbDestination);
739  rv=GWEN_Xml2Db_HandleChildren(ctx, xmlNodeSchema);
741 
742  if (rv<0) {
743  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
744  return rv;
745  }
746 
747  return 0;
748 }
749 
750 
751 
GWEN_XML2DB_CONTEXT * GWEN_Xml2Db_Context_new(GWEN_XMLNODE *documentRoot, GWEN_DB_NODE *dbRoot)
Definition: xml2db.c:43
int GWEN_DB_ReplaceVars(GWEN_DB_NODE *db, const char *s, GWEN_BUFFER *dbuf)
Definition: db.c:1949
int GWEN_Xml2Db_Handle_XmlForEvery(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
Definition: xml2db.c:296
char * GWEN_Buffer_GetStart(const GWEN_BUFFER *bf)
Definition: buffer.c:231
void GWEN_Text_CondenseBuffer(GWEN_BUFFER *buf)
Definition: text.c:1620
GWEN_DATE * GWEN_Date_fromStringWithTemplate(const char *s, const char *tmpl)
Definition: gwendate.c:377
struct GWEN_DB_NODE GWEN_DB_NODE
Definition: db.h:228
void GWEN_DB_Group_free(GWEN_DB_NODE *n)
Definition: db.c:419
#define GWEN_ERROR_INVALID
Definition: error.h:67
const char * GWEN_XMLNode_GetProperty(const GWEN_XMLNODE *n, const char *name, const char *defaultValue)
Definition: xml.c:239
GWEN_XMLNODE * GWEN_XMLNode_FindNextTag(const GWEN_XMLNODE *n, const char *tname, const char *pname, const char *pvalue)
Definition: xml.c:754
int GWEN_Xml2Db_Handle_XmlIfHasCharData(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
Definition: xml2db.c:557
GWEN_XMLNODE_LIST2 * GWEN_XMLNode_List2_new()
void GWEN_Xml2Db_Context_EnterDocNode(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
Definition: xml2db.c:77
#define GWEN_FREE_OBJECT(varname)
Definition: memory.h:61
#define NULL
Definition: binreloc.c:300
#define GWEN_PATH_FLAGS_CREATE_GROUP
Definition: path.h:96
int GWEN_Xml2Db_Handle_XmlIfNotCharDataMatches(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
Definition: xml2db.c:520
int GWEN_Xml2Db_Handle_DbSetTempCharValue(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
Definition: xml2db.c:476
void GWEN_XMLNode_List2_free(GWEN_XMLNODE_LIST2 *l)
#define GWEN_LOGDOMAIN
Definition: logger.h:35
GWEN_BUFFER * GWEN_Buffer_new(char *buffer, uint32_t size, uint32_t used, int take)
Definition: buffer.c:38
int GWEN_Xml2Db_Handle_XmlIfPathExists(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
Definition: xml2db.c:616
GWEN_XMLNODE * GWEN_XMLNode_FindFirstTag(const GWEN_XMLNODE *n, const char *tname, const char *pname, const char *pvalue)
Definition: xml.c:736
#define GWEN_NEW_OBJECT(typ, varname)
Definition: memory.h:55
int GWEN_XMLNode_GetIntProperty(const GWEN_XMLNODE *n, const char *name, int defaultValue)
Definition: xml.c:263
void GWEN_Xml2Db_Context_free(GWEN_XML2DB_CONTEXT *ctx)
Definition: xml2db.c:64
const char * GWEN_Xml2Db_GetCharValueByPath(GWEN_XMLNODE *xmlNode, const char *path, const char *defValue)
Definition: xml2db.c:108
GWEN_XMLNODE * GWEN_XMLNode_GetNextTag(const GWEN_XMLNODE *n)
Definition: xml.c:672
void GWEN_XMLNode_List2_PopBack(GWEN_XMLNODE_LIST2 *l)
int GWEN_Xml2Db(GWEN_XMLNODE *xmlNodeDocument, GWEN_XMLNODE *xmlNodeSchema, GWEN_DB_NODE *dbDestination)
Definition: xml2db.c:731
void GWEN_Date_free(GWEN_DATE *gd)
Definition: gwendate.c:237
GWEN_XMLNODE * GWEN_XMLNode_GetNodeByXPath(GWEN_XMLNODE *n, const char *path, uint32_t flags)
Definition: xml.c:1271
int GWEN_Buffer_AppendByte(GWEN_BUFFER *bf, char c)
Definition: buffer.c:390
const char * GWEN_DB_GetCharValue(GWEN_DB_NODE *n, const char *path, int idx, const char *defVal)
Definition: db.c:969
GWEN_DB_NODE * GWEN_DB_GetGroup(GWEN_DB_NODE *n, uint32_t flags, const char *path)
Definition: db.c:1379
void GWEN_Buffer_free(GWEN_BUFFER *bf)
Definition: buffer.c:85
int GWEN_DB_DeleteVar(GWEN_DB_NODE *n, const char *path)
Definition: db.c:897
struct GWEN_BUFFER GWEN_BUFFER
A dynamically resizeable text buffer.
Definition: buffer.h:38
int GWEN_Xml2Db_Handle_XmlIfNotHasCharData(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
Definition: xml2db.c:588
const char * GWEN_Date_GetString(const GWEN_DATE *gd)
Definition: gwendate.c:323
int GWEN_XMLNode_GetXPath(const GWEN_XMLNODE *n1, const GWEN_XMLNODE *n2, GWEN_BUFFER *nbuf)
Definition: xml.c:1057
void GWEN_Xml2Db_Context_LeaveDocNode(GWEN_XML2DB_CONTEXT *ctx)
Definition: xml2db.c:88
int GWEN_Xml2Db_Handle_XmlIfNotPathExists(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
Definition: xml2db.c:645
int GWEN_Xml2Db_Handle_DbSetCharValue_internal(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode, GWEN_DB_NODE *dbCurrent)
Definition: xml2db.c:410
#define DBG_ERROR(dbg_logger, format, args...)
Definition: debug.h:97
GWEN_XMLNODE * GWEN_XMLNode_GetFirstTag(const GWEN_XMLNODE *n)
Definition: xml.c:665
const char * GWEN_XMLNode_GetData(const GWEN_XMLNODE *n)
Definition: xml.c:370
int GWEN_Text_ComparePattern(const char *w, const char *p, int sensecase)
Definition: text.c:1208
int GWEN_DB_SetCharValue(GWEN_DB_NODE *n, uint32_t flags, const char *path, const char *val)
Definition: db.c:995
int GWEN_Xml2Db_Handle_DbSetCharValue(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
Definition: xml2db.c:469
#define GWEN_PATH_FLAGS_PATHMUSTEXIST
Definition: path.h:66
#define DBG_INFO(dbg_logger, format, args...)
Definition: debug.h:178
void GWEN_DB_UnlinkGroup(GWEN_DB_NODE *n)
Definition: db.c:1552
GWEN_XMLNODE * GWEN_XMLNode_List2_GetBack(GWEN_XMLNODE_LIST2 *l)
void GWEN_XMLNode_List2_PushBack(GWEN_XMLNODE_LIST2 *l, GWEN_XMLNODE *p)
const char * GWEN_XMLNode_GetCharValueByPath(GWEN_XMLNODE *n, const char *name, const char *defValue)
Definition: xml.c:941
GWEN_DB_NODE * GWEN_DB_Group_new(const char *name)
Definition: db.c:171
int GWEN_Xml2Db_Handle_XmlEnter(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
Definition: xml2db.c:262
int GWEN_Xml2Db_Handle_DbCreateAndEnterTempGroup(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
Definition: xml2db.c:371
int GWEN_Xml2Db_Handle_DbCreateAndEnterGroup(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
Definition: xml2db.c:337
int GWEN_Xml2Db_Handle_XmlIfCharDataMatches(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
Definition: xml2db.c:483
int GWEN_Xml2Db_ConvertAndSetCharValue(GWEN_UNUSED GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode, GWEN_DB_NODE *dbCurrent, const char *value)
Definition: xml2db.c:149
struct GWEN__XMLNODE GWEN_XMLNODE
Definition: xml.h:149
#define GWEN_UNUSED
int GWEN_Xml2Db_HandleChildren(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
Definition: xml2db.c:675
int GWEN_Buffer_AppendString(GWEN_BUFFER *bf, const char *buffer)
Definition: buffer.c:985
#define GWEN_DB_FLAGS_DEFAULT
Definition: db.h:168
struct GWEN_DATE GWEN_DATE
Definition: gwendate.h:34