gwenhywfar  4.99.15beta
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_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode, GWEN_DB_NODE *dbCurrent,
150  const char *value)
151 {
152  if (value && *value) {
153  const char *name;
154  const char *typ;
155  const char *mode;
156  int doTrim=0;
157  GWEN_BUFFER *vbuf;
158  GWEN_BUFFER *resultBuf;
159 
160  doTrim=GWEN_XMLNode_GetIntProperty(xmlNode, "trim", 0);
161  vbuf=GWEN_Buffer_new(0, 256, 0, 1);
162  resultBuf=GWEN_Buffer_new(0, 256, 0, 1);
163 
164  name=GWEN_XMLNode_GetProperty(xmlNode, "name", NULL);
165  if (!(name && *name)) {
166  DBG_ERROR(GWEN_LOGDOMAIN, "Missing or empty name in \"SetCharValue\"");
167  GWEN_Buffer_free(resultBuf);
168  GWEN_Buffer_free(vbuf);
169  return GWEN_ERROR_INVALID;
170  }
171 
172  typ=GWEN_XMLNode_GetProperty(xmlNode, "type", "string");
173  if (!(typ && *typ)) {
174  DBG_ERROR(GWEN_LOGDOMAIN, "Empty type in \"SetCharValue\"");
175  GWEN_Buffer_free(resultBuf);
176  GWEN_Buffer_free(vbuf);
177  return GWEN_ERROR_INVALID;
178  }
179 
180  mode=GWEN_XMLNode_GetProperty(xmlNode, "mode", "add");
181 
182  if (strcasecmp(typ, "string")==0) {
183  GWEN_Buffer_AppendString(vbuf, value);
184  if (doTrim)
186  }
187  else if (strcasecmp(typ, "date")==0) {
188  const char *tmpl;
189  GWEN_DATE *dt=NULL;
190 
191  tmpl=GWEN_XMLNode_GetProperty(xmlNode, "template", "YYYYMMDD");
192  if (!(tmpl && *tmpl)) {
193  DBG_ERROR(GWEN_LOGDOMAIN, "Empty template in \"SetCharValue\"");
194  GWEN_Buffer_free(resultBuf);
195  GWEN_Buffer_free(vbuf);
196  return GWEN_ERROR_INVALID;
197  }
198 
199  dt=GWEN_Date_fromStringWithTemplate(value, tmpl);
200  if (dt) {
202  GWEN_Date_free(dt);
203  }
204  }
205 
206  if (strcasecmp(mode, "add")==0) {
207  /* just exchange the buffer */
208  GWEN_Buffer_free(resultBuf);
209  resultBuf=vbuf;
210  vbuf=NULL;
211  }
212  else if (strcasecmp(mode, "append")==0) {
213  const char *s;
214 
215  s=GWEN_DB_GetCharValue(dbCurrent, name, 0, NULL);
216  if (s && *s) {
217  const char *delimiter;
218 
219  /* write previous data into resultBuffer */
220  GWEN_Buffer_AppendString(resultBuf, s);
221 
222  /* possibly write delimiter into resultBuffer */
223  delimiter=GWEN_XMLNode_GetProperty(xmlNode, "delimiter", NULL);
224  if (delimiter && *delimiter) {
225  if (strcasecmp(delimiter, "\\n")==0)
226  GWEN_Buffer_AppendByte(resultBuf, '\n');
227  else if (strcasecmp(delimiter, "\\t")==0)
228  GWEN_Buffer_AppendByte(resultBuf, '\t');
229  else
230  GWEN_Buffer_AppendString(resultBuf, delimiter);
231  }
232  } /* if previous value */
233  /* write value into resultBuffer */
235 
236  GWEN_DB_DeleteVar(dbCurrent, name);
237  }
238  else if (strcasecmp(mode, "replace")==0) {
239  /* just exchange the buffer */
240  GWEN_Buffer_free(resultBuf);
241  resultBuf=vbuf;
242  vbuf=NULL;
243  GWEN_DB_DeleteVar(dbCurrent, name);
244  }
245 
246  DBG_INFO(GWEN_LOGDOMAIN, "Setting value: %s = %s", name, GWEN_Buffer_GetStart(resultBuf));
247 
249  GWEN_Buffer_free(resultBuf);
250  GWEN_Buffer_free(vbuf);
251  }
252  return 0;
253 }
254 
255 
256 
257 
258 
259 
260 
261 int GWEN_Xml2Db_Handle_XmlEnter(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
262 {
263  const char *path;
264  GWEN_XMLNODE *n;
265  int rv;
266 
267  path=GWEN_XMLNode_GetProperty(xmlNode, "path", NULL);
268  if (path==NULL) {
269  DBG_ERROR(GWEN_LOGDOMAIN, "Missing path in \"EnterPath\"");
270  return GWEN_ERROR_INVALID;
271  }
272 
273  n=GWEN_XMLNode_GetNodeByXPath(ctx->currentDocNode, path, GWEN_PATH_FLAGS_PATHMUSTEXIST);
274  if (n==NULL) {
275  DBG_ERROR(GWEN_LOGDOMAIN, "Path \"%s\" does not exist", path);
276  return GWEN_ERROR_INVALID;
277  }
278 
279  /* enter given document node */
281 
282  rv=GWEN_Xml2Db_HandleChildren(ctx, xmlNode);
283  if (rv<0) {
284  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
285  return rv;
286  }
287 
288  /* leave given document node, re-select previously active one, thus restoring status from the beginning */
290  return 0;
291 }
292 
293 
294 
295 int GWEN_Xml2Db_Handle_XmlForEvery(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
296 {
297  const char *path;
298  GWEN_XMLNODE *n;
299  int rv;
300 
301  path=GWEN_XMLNode_GetProperty(xmlNode, "name", NULL);
302  if (path==NULL) {
303  DBG_ERROR(GWEN_LOGDOMAIN, "Missing name in \"ForEvery\"");
304  return GWEN_ERROR_INVALID;
305  }
306 
307  n=GWEN_XMLNode_FindFirstTag(ctx->currentDocNode, path, NULL, NULL);
308  if (n==NULL) {
309  DBG_ERROR(GWEN_LOGDOMAIN, "Path \"%s\" not found", path);
310  /* GWEN_XMLNode_Dump(ctx->currentDocNode, 2); */
311  }
312  while (n) {
313 
314  /* enter given document node */
316 
317  /* handle all children of this parser XML node with the current document node */
318  rv=GWEN_Xml2Db_HandleChildren(ctx, xmlNode);
319 
320  /* leave given document node, re-select previously active one, thus restoring status from the beginning */
322 
323  if (rv<0) {
324  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
325  return rv;
326  }
327 
328  n=GWEN_XMLNode_FindNextTag(n, path, NULL, NULL);
329  }
330 
331  return 0;
332 }
333 
334 
335 
336 int GWEN_Xml2Db_Handle_DbCreateAndEnterGroup(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
337 {
338  const char *name;
339  GWEN_DB_NODE *dbLast;
340  int rv;
341 
342  name=GWEN_XMLNode_GetProperty(xmlNode, "name", NULL);
343  if (!(name && *name)) {
344  DBG_ERROR(GWEN_LOGDOMAIN, "Missing or empty name in \"CreateAnEnterDbGroup\"");
345  return GWEN_ERROR_INVALID;
346  }
347 
348  /* push group */
349  dbLast=ctx->currentDbGroup;
350 
351  /* create group */
352  ctx->currentDbGroup=GWEN_DB_GetGroup(dbLast, GWEN_PATH_FLAGS_CREATE_GROUP, name);
353 
354  /* handle children (nothing special here) */
355  rv=GWEN_Xml2Db_HandleChildren(ctx, xmlNode);
356 
357  /* pop group */
358  ctx->currentDbGroup=dbLast;
359 
360  if (rv<0) {
361  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
362  return rv;
363  }
364 
365  return 0;
366 }
367 
368 
369 
370 int GWEN_Xml2Db_Handle_DbCreateAndEnterTempGroup(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
371 {
372  const char *name;
373  GWEN_DB_NODE *dbLast;
374  int rv;
375 
376  name=GWEN_XMLNode_GetProperty(xmlNode, "name", NULL);
377  if (!(name && *name)) {
378  DBG_ERROR(GWEN_LOGDOMAIN, "Missing or empty name in \"CreateAnEnterTempDbGroup\"");
379  return GWEN_ERROR_INVALID;
380  }
381 
382  /* push group */
383  dbLast=ctx->currentTempDbGroup;
384 
385  /* create group */
386  ctx->currentTempDbGroup=GWEN_DB_GetGroup(dbLast, GWEN_PATH_FLAGS_CREATE_GROUP, name);
387  assert(ctx->currentTempDbGroup);
388 
389  /* handle children (nothing special here) */
390  rv=GWEN_Xml2Db_HandleChildren(ctx, xmlNode);
391 
392  /* delete temp group */
393  GWEN_DB_UnlinkGroup(ctx->currentTempDbGroup);
394  GWEN_DB_Group_free(ctx->currentTempDbGroup);
395 
396  /* pop group */
397  ctx->currentTempDbGroup=dbLast;
398 
399  if (rv<0) {
400  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
401  return rv;
402  }
403 
404  return 0;
405 }
406 
407 
408 
409 int GWEN_Xml2Db_Handle_DbSetCharValue_internal(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode,
410  GWEN_DB_NODE *dbCurrent)
411 {
412  const char *name;
413  const char *value;
414 
415  name=GWEN_XMLNode_GetProperty(xmlNode, "name", NULL);
416  if (!(name && *name)) {
417  DBG_ERROR(GWEN_LOGDOMAIN, "Missing or empty name in \"SetCharValue\"");
418  return GWEN_ERROR_INVALID;
419  }
420 
421  value=GWEN_XMLNode_GetProperty(xmlNode, "value", NULL);
422  if (value) {
423  GWEN_BUFFER *dbuf;
424  int rv;
425 
426  dbuf=GWEN_Buffer_new(0, 256, 0, 1);
427  rv=GWEN_DB_ReplaceVars(ctx->currentTempDbGroup, value, dbuf);
428  if (rv<0) {
429  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
430  GWEN_Buffer_free(dbuf);
431  return rv;
432  }
433  GWEN_Xml2Db_ConvertAndSetCharValue(ctx, xmlNode, dbCurrent, GWEN_Buffer_GetStart(dbuf));
434  GWEN_Buffer_free(dbuf);
435  }
436  else {
437  const char *path;
438 
439  path=GWEN_XMLNode_GetProperty(xmlNode, "path", NULL);
440  if (!(path && *path)) {
441  DBG_ERROR(GWEN_LOGDOMAIN, "Missing or empty path in \"SetCharValue\"");
442  return GWEN_ERROR_INVALID;
443  }
444 
445  value=GWEN_Xml2Db_GetCharValueByPath(ctx->currentDocNode, path, NULL);
446  if (value && *value) {
447  GWEN_Xml2Db_ConvertAndSetCharValue(ctx, xmlNode, dbCurrent, value);
448  }
449  else {
450  GWEN_BUFFER *tbuf;
451 
452  tbuf=GWEN_Buffer_new(0, 256, 0, 1);
453 
454  GWEN_XMLNode_GetXPath(NULL, ctx->currentDocNode, tbuf);
455 
456  DBG_ERROR(GWEN_LOGDOMAIN, "No value in path \"%s\" (%s)", path, GWEN_Buffer_GetStart(tbuf));
457  GWEN_Buffer_free(tbuf);
458 
459  /* GWEN_XMLNode_Dump(ctx->currentDocNode, 2); */
460  }
461  }
462 
463  return 0;
464 }
465 
466 
467 
468 int GWEN_Xml2Db_Handle_DbSetCharValue(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
469 {
470  return GWEN_Xml2Db_Handle_DbSetCharValue_internal(ctx, xmlNode, ctx->currentDbGroup);
471 }
472 
473 
474 
475 int GWEN_Xml2Db_Handle_DbSetTempCharValue(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
476 {
477  return GWEN_Xml2Db_Handle_DbSetCharValue_internal(ctx, xmlNode, ctx->currentTempDbGroup);
478 }
479 
480 
481 
482 int GWEN_Xml2Db_Handle_XmlIfCharDataMatches(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
483 {
484  const char *pattern;
485  const char *path;
486  const char *value;
487 
488  path=GWEN_XMLNode_GetProperty(xmlNode, "path", NULL);
489  if (!(path && *path)) {
490  DBG_ERROR(GWEN_LOGDOMAIN, "Missing or empty path in \"IfCharDataMatches\"");
491  return GWEN_ERROR_INVALID;
492  }
493 
494  pattern=GWEN_XMLNode_GetProperty(xmlNode, "pattern", NULL);
495  if (!(pattern && *pattern)) {
496  DBG_ERROR(GWEN_LOGDOMAIN, "Missing or empty pattern in \"IfCharDataMatches\"");
497  return GWEN_ERROR_INVALID;
498  }
499 
500  value=GWEN_Xml2Db_GetCharValueByPath(ctx->currentDocNode, path, NULL);
501  if (value) {
502  if (-1!=GWEN_Text_ComparePattern(value, pattern, 0)) {
503  int rv;
504 
505  /* pattern matches, handle children */
506  rv=GWEN_Xml2Db_HandleChildren(ctx, xmlNode);
507  if (rv<0) {
508  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
509  return rv;
510  }
511  }
512  }
513 
514  return 0;
515 }
516 
517 
518 
519 int GWEN_Xml2Db_Handle_XmlIfNotCharDataMatches(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
520 {
521  const char *pattern;
522  const char *path;
523  const char *value;
524 
525  path=GWEN_XMLNode_GetProperty(xmlNode, "path", NULL);
526  if (!(path && *path)) {
527  DBG_ERROR(GWEN_LOGDOMAIN, "Missing or empty path in \"IfNotCharDataMatches\"");
528  return GWEN_ERROR_INVALID;
529  }
530 
531  pattern=GWEN_XMLNode_GetProperty(xmlNode, "pattern", NULL);
532  if (!(pattern && *pattern)) {
533  DBG_ERROR(GWEN_LOGDOMAIN, "Missing or empty pattern in \"IfNotCharDataMatches\"");
534  return GWEN_ERROR_INVALID;
535  }
536 
537  value=GWEN_Xml2Db_GetCharValueByPath(ctx->currentDocNode, path, NULL);
538  if (value) {
539  if (-1==GWEN_Text_ComparePattern(value, pattern, 0)) {
540  int rv;
541 
542  /* pattern doesnt match, handle children */
543  rv=GWEN_Xml2Db_HandleChildren(ctx, xmlNode);
544  if (rv<0) {
545  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
546  return rv;
547  }
548  }
549  }
550 
551  return 0;
552 }
553 
554 
555 
556 int GWEN_Xml2Db_Handle_XmlIfHasCharData(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
557 {
558  const char *path;
559  const char *value;
560 
561  path=GWEN_XMLNode_GetProperty(xmlNode, "path", NULL);
562  if (!(path && *path)) {
563  DBG_ERROR(GWEN_LOGDOMAIN, "Missing or empty path in \"IfCharDataMatches\"");
564  return GWEN_ERROR_INVALID;
565  }
566 
567  value=GWEN_Xml2Db_GetCharValueByPath(ctx->currentDocNode, path, NULL);
568  if (value && *value) {
569  int rv;
570 
571  /* there is a value, handle children */
572  rv=GWEN_Xml2Db_HandleChildren(ctx, xmlNode);
573  if (rv<0) {
574  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
575  return rv;
576  }
577  }
578  else {
579  DBG_INFO(GWEN_LOGDOMAIN, "No value for path \"%s\"", path);
580  }
581 
582  return 0;
583 }
584 
585 
586 
587 int GWEN_Xml2Db_Handle_XmlIfNotHasCharData(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
588 {
589  const char *path;
590  const char *value;
591 
592  path=GWEN_XMLNode_GetProperty(xmlNode, "path", NULL);
593  if (!(path && *path)) {
594  DBG_ERROR(GWEN_LOGDOMAIN, "Missing or empty path in \"IfNotCharDataMatches\"");
595  return GWEN_ERROR_INVALID;
596  }
597 
598  value=GWEN_Xml2Db_GetCharValueByPath(ctx->currentDocNode, path, NULL);
599  if (!(value && *value)) {
600  int rv;
601 
602  /* there is a value, handle children */
603  rv=GWEN_Xml2Db_HandleChildren(ctx, xmlNode);
604  if (rv<0) {
605  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
606  return rv;
607  }
608  }
609 
610  return 0;
611 }
612 
613 
614 
615 int GWEN_Xml2Db_Handle_XmlIfPathExists(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
616 {
617  const char *path;
618 
619  path=GWEN_XMLNode_GetProperty(xmlNode, "path", NULL);
620  if (!(path && *path)) {
621  DBG_ERROR(GWEN_LOGDOMAIN, "Missing or empty path in \"IfPathExists\"");
622  return GWEN_ERROR_INVALID;
623  }
624 
625  if (GWEN_XMLNode_GetNodeByXPath(ctx->currentDocNode, path, GWEN_PATH_FLAGS_PATHMUSTEXIST)) {
626  int rv;
627 
628  /* path exists, handle children */
629  rv=GWEN_Xml2Db_HandleChildren(ctx, xmlNode);
630  if (rv<0) {
631  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
632  return rv;
633  }
634  }
635  else {
636  DBG_INFO(GWEN_LOGDOMAIN, "Path \"%s\" does not exist", path);
637  }
638 
639  return 0;
640 }
641 
642 
643 
644 int GWEN_Xml2Db_Handle_XmlIfNotPathExists(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
645 {
646  const char *path;
647 
648  path=GWEN_XMLNode_GetProperty(xmlNode, "path", NULL);
649  if (!(path && *path)) {
650  DBG_ERROR(GWEN_LOGDOMAIN, "Missing or empty path in \"IfNotPathExists\"");
651  return GWEN_ERROR_INVALID;
652  }
653 
654  if (NULL==GWEN_XMLNode_GetNodeByXPath(ctx->currentDocNode, path, GWEN_PATH_FLAGS_PATHMUSTEXIST)) {
655  int rv;
656 
657  /* path does not exist, handle children */
658  rv=GWEN_Xml2Db_HandleChildren(ctx, xmlNode);
659  if (rv<0) {
660  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
661  return rv;
662  }
663  }
664  else {
665  DBG_INFO(GWEN_LOGDOMAIN, "Path \"%s\" exists", path);
666  }
667 
668  return 0;
669 }
670 
671 
672 
673 
674 int GWEN_Xml2Db_HandleChildren(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
675 {
676  GWEN_XMLNODE *n;
677 
678  n=GWEN_XMLNode_GetFirstTag(xmlNode);
679  while (n) {
680  const char *name;
681 
682  name=GWEN_XMLNode_GetData(n);
683  if (name && *name) {
684  int rv;
685 
686  DBG_INFO(GWEN_LOGDOMAIN, "Handling element \"%s\"", name);
687  if (strcasecmp(name, "XmlEnter")==0)
688  rv=GWEN_Xml2Db_Handle_XmlEnter(ctx, n);
689  else if (strcasecmp(name, "XmlForEvery")==0)
691  else if (strcasecmp(name, "DbCreateAndEnterGroup")==0)
693  else if (strcasecmp(name, "DbCreateAndEnterTempGroup")==0)
695  else if (strcasecmp(name, "DbSetCharValue")==0)
697  else if (strcasecmp(name, "DbSetTempCharValue")==0)
699  else if (strcasecmp(name, "XmlIfCharDataMatches")==0)
701  else if (strcasecmp(name, "XmlIfNotCharDataMatches")==0)
703  else if (strcasecmp(name, "XmlIfHasCharData")==0)
705  else if (strcasecmp(name, "XmlIfNotHasCharData")==0)
707  else if (strcasecmp(name, "XmlIfPathExists")==0)
709  else if (strcasecmp(name, "XmlIfNotPathExists")==0)
711  else {
712  DBG_ERROR(GWEN_LOGDOMAIN, "Unknown element \"%s\", aborting", name);
713  return GWEN_ERROR_INVALID;
714  }
715  if (rv<0) {
716  DBG_ERROR(GWEN_LOGDOMAIN, "Error in element \"%s\", aborting", name);
717  return rv;
718  }
719  }
720 
722  }
723 
724  return 0;
725 }
726 
727 
728 
729 
730 int GWEN_Xml2Db(GWEN_XMLNODE *xmlNodeDocument,
731  GWEN_XMLNODE *xmlNodeSchema,
732  GWEN_DB_NODE *dbDestination)
733 {
734  GWEN_XML2DB_CONTEXT *ctx;
735  int rv;
736 
737  ctx=GWEN_Xml2Db_Context_new(xmlNodeDocument, dbDestination);
738  rv=GWEN_Xml2Db_HandleChildren(ctx, xmlNodeSchema);
740 
741  if (rv<0) {
742  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
743  return rv;
744  }
745 
746  return 0;
747 }
748 
749 
750 
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:1938
int GWEN_Xml2Db_Handle_XmlForEvery(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
Definition: xml2db.c:295
char * GWEN_Buffer_GetStart(const GWEN_BUFFER *bf)
Definition: buffer.c:235
void GWEN_Text_CondenseBuffer(GWEN_BUFFER *buf)
Definition: text.c:1593
GWEN_DATE * GWEN_Date_fromStringWithTemplate(const char *s, const char *tmpl)
Definition: gwendate.c:375
struct GWEN_DB_NODE GWEN_DB_NODE
Definition: db.h:228
void GWEN_DB_Group_free(GWEN_DB_NODE *n)
Definition: db.c:408
#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:556
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:92
#define NULL
Definition: binreloc.c:297
#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:519
int GWEN_Xml2Db_Handle_DbSetTempCharValue(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
Definition: xml2db.c:475
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:615
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:86
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:730
void GWEN_Date_free(GWEN_DATE *gd)
Definition: gwendate.c:235
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:399
const char * GWEN_DB_GetCharValue(GWEN_DB_NODE *n, const char *path, int idx, const char *defVal)
Definition: db.c:958
GWEN_DB_NODE * GWEN_DB_GetGroup(GWEN_DB_NODE *n, uint32_t flags, const char *path)
Definition: db.c:1368
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:886
struct GWEN_BUFFER GWEN_BUFFER
A dynamically resizeable text buffer.
Definition: buffer.h:41
int GWEN_Xml2Db_Handle_XmlIfNotHasCharData(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
Definition: xml2db.c:587
const char * GWEN_Date_GetString(const GWEN_DATE *gd)
Definition: gwendate.c:321
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:644
int GWEN_Xml2Db_Handle_DbSetCharValue_internal(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode, GWEN_DB_NODE *dbCurrent)
Definition: xml2db.c:409
#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:1181
int GWEN_DB_SetCharValue(GWEN_DB_NODE *n, uint32_t flags, const char *path, const char *val)
Definition: db.c:984
int GWEN_Xml2Db_Handle_DbSetCharValue(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
Definition: xml2db.c:468
#define GWEN_PATH_FLAGS_PATHMUSTEXIST
Definition: path.h:66
#define DBG_INFO(dbg_logger, format, args...)
Definition: debug.h:177
void GWEN_DB_UnlinkGroup(GWEN_DB_NODE *n)
Definition: db.c:1541
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:160
int GWEN_Xml2Db_Handle_XmlEnter(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
Definition: xml2db.c:261
int GWEN_Xml2Db_Handle_DbCreateAndEnterTempGroup(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
Definition: xml2db.c:370
int GWEN_Xml2Db_Handle_DbCreateAndEnterGroup(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
Definition: xml2db.c:336
int GWEN_Xml2Db_Handle_XmlIfCharDataMatches(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
Definition: xml2db.c:482
struct GWEN__XMLNODE GWEN_XMLNODE
Definition: xml.h:148
int GWEN_Xml2Db_HandleChildren(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
Definition: xml2db.c:674
int GWEN_Buffer_AppendString(GWEN_BUFFER *bf, const char *buffer)
Definition: buffer.c:1062
#define GWEN_DB_FLAGS_DEFAULT
Definition: db.h:168
struct GWEN_DATE GWEN_DATE
Definition: gwendate.h:34
int GWEN_Xml2Db_ConvertAndSetCharValue(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode, GWEN_DB_NODE *dbCurrent, const char *value)
Definition: xml2db.c:149