gwenhywfar  5.3.0
xml2db_todb.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 
44 /* ------------------------------------------------------------------------------------------------
45  * forward declarations
46  * ------------------------------------------------------------------------------------------------
47  */
48 
49 static int _handleChildren_toDb(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode);
50 static const char *_getCharValueByPath(GWEN_XMLNODE *xmlNode, const char *path, const char *defValue);
51 static int _convertAndSetCharValue(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode, GWEN_DB_NODE *dbCurrent, const char *value);
52 
53 static int _handleDbSetCharValue_internal(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode, GWEN_DB_NODE *dbCurrent);
54 
55 
56 static int _handleXmlEnter(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode);
57 static int _handleXmlForEvery(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode);
58 static int _handleDbCreateAndEnterGroup(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode);
59 static int _handleDbCreateAndEnterTempGroup(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode);
60 static int _handleDbSetCharValue(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode);
61 static int _handleDbSetTempCharValue(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode);
62 static int _handleXmlIfCharDataMatches(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode);
63 static int _handleXmlIfNotCharDataMatches(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode);
64 static int _handleXmlIfHasCharData(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode);
65 static int _handleXmlIfNotHasCharData(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode);
66 static int _handleXmlIfPathExists(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode);
67 static int _handleXmlIfNotPathExists(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode);
68 
69 
70 
71 
72 
73 /* ------------------------------------------------------------------------------------------------
74  * implementations
75  * ------------------------------------------------------------------------------------------------
76  */
77 
78 
79 int GWEN_Xml2Db(GWEN_XMLNODE *xmlNodeDocument,
80  GWEN_XMLNODE *xmlNodeSchema,
81  GWEN_DB_NODE *dbDestination)
82 {
83  GWEN_XML2DB_CONTEXT *ctx;
84  int rv;
85 
86  ctx=GWEN_Xml2Db_Context_new(xmlNodeDocument, dbDestination);
87  ctx->handleChildrenFn=_handleChildren_toDb;
88  rv=GWEN_Xml2Db_Context_HandleChildren(ctx, xmlNodeSchema);
90 
91  if (rv<0) {
92  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
93  return rv;
94  }
95 
96  return 0;
97 }
98 
99 
100 
101 
102 
103 const char *_getCharValueByPath(GWEN_XMLNODE *xmlNode, const char *path, const char *defValue)
104 {
105  const char *s;
106 
107  s=strchr(path, '@');
108  if (s) {
109  int idx;
110  char *cpyOfPath;
111  char *property;
112  GWEN_XMLNODE *n;
113 
114 
115  idx=s-path;
116  cpyOfPath=strdup(path);
117  assert(cpyOfPath);
118  cpyOfPath[idx]=0;
119  property=cpyOfPath+idx+1;
120 
121  if (*cpyOfPath) {
123  }
124  else
125  n=xmlNode;
126 
127  if (n) {
128  const char *result;
129 
130  result=GWEN_XMLNode_GetProperty(n, property, defValue);
131  DBG_INFO(GWEN_LOGDOMAIN, "Got XML property: %s = %s (%s)", property, result, path);
132  free(cpyOfPath);
133  return result;
134  }
135  free(cpyOfPath);
136  return defValue;
137  }
138  else
139  return GWEN_XMLNode_GetCharValueByPath(xmlNode, path, defValue);
140 }
141 
142 
143 /* TODO: optimize later */
144 int _convertAndSetCharValue(GWEN_UNUSED GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode,
145  GWEN_DB_NODE *dbCurrent,
146  const char *value)
147 {
148  if (value && *value) {
149  const char *name;
150  const char *typ;
151  const char *mode;
152  int doTrim=0;
153  GWEN_BUFFER *vbuf;
154  GWEN_BUFFER *resultBuf;
155 
156  doTrim=GWEN_XMLNode_GetIntProperty(xmlNode, "trim", 0);
157  vbuf=GWEN_Buffer_new(0, 256, 0, 1);
158  resultBuf=GWEN_Buffer_new(0, 256, 0, 1);
159 
160  name=GWEN_XMLNode_GetProperty(xmlNode, "name", NULL);
161  if (!(name && *name)) {
162  DBG_ERROR(GWEN_LOGDOMAIN, "Missing or empty name in \"SetCharValue\"");
163  GWEN_Buffer_free(resultBuf);
164  GWEN_Buffer_free(vbuf);
165  return GWEN_ERROR_INVALID;
166  }
167 
168  typ=GWEN_XMLNode_GetProperty(xmlNode, "type", "string");
169  if (!(typ && *typ)) {
170  DBG_ERROR(GWEN_LOGDOMAIN, "Empty type in \"SetCharValue\"");
171  GWEN_Buffer_free(resultBuf);
172  GWEN_Buffer_free(vbuf);
173  return GWEN_ERROR_INVALID;
174  }
175 
176  mode=GWEN_XMLNode_GetProperty(xmlNode, "mode", "add");
177 
178  if (strcasecmp(typ, "string")==0) {
179  GWEN_Buffer_AppendString(vbuf, value);
180  if (doTrim)
182  }
183  else if (strcasecmp(typ, "date")==0) {
184  const char *tmpl;
185  GWEN_DATE *dt=NULL;
186 
187  tmpl=GWEN_XMLNode_GetProperty(xmlNode, "template", "YYYYMMDD");
188  if (!(tmpl && *tmpl)) {
189  DBG_ERROR(GWEN_LOGDOMAIN, "Empty template in \"SetCharValue\"");
190  GWEN_Buffer_free(resultBuf);
191  GWEN_Buffer_free(vbuf);
192  return GWEN_ERROR_INVALID;
193  }
194 
195  dt=GWEN_Date_fromStringWithTemplate(value, tmpl);
196  if (dt) {
198  GWEN_Date_free(dt);
199  }
200  }
201 
202  if (strcasecmp(mode, "add")==0) {
203  /* just exchange the buffer */
204  GWEN_Buffer_free(resultBuf);
205  resultBuf=vbuf;
206  vbuf=NULL;
207  }
208  else if (strcasecmp(mode, "append")==0) {
209  const char *s;
210 
211  s=GWEN_DB_GetCharValue(dbCurrent, name, 0, NULL);
212  if (s && *s) {
213  const char *delimiter;
214 
215  /* write previous data into resultBuffer */
216  GWEN_Buffer_AppendString(resultBuf, s);
217 
218  /* possibly write delimiter into resultBuffer */
219  delimiter=GWEN_XMLNode_GetProperty(xmlNode, "delimiter", NULL);
220  if (delimiter && *delimiter) {
221  if (strcasecmp(delimiter, "\\n")==0)
222  GWEN_Buffer_AppendByte(resultBuf, '\n');
223  else if (strcasecmp(delimiter, "\\t")==0)
224  GWEN_Buffer_AppendByte(resultBuf, '\t');
225  else
226  GWEN_Buffer_AppendString(resultBuf, delimiter);
227  }
228  } /* if previous value */
229  /* write value into resultBuffer */
231 
232  GWEN_DB_DeleteVar(dbCurrent, name);
233  }
234  else if (strcasecmp(mode, "replace")==0) {
235  /* just exchange the buffer */
236  GWEN_Buffer_free(resultBuf);
237  resultBuf=vbuf;
238  vbuf=NULL;
239  GWEN_DB_DeleteVar(dbCurrent, name);
240  }
241 
242  DBG_INFO(GWEN_LOGDOMAIN, "Setting value: %s = %s", name, GWEN_Buffer_GetStart(resultBuf));
243 
245  GWEN_Buffer_free(resultBuf);
246  GWEN_Buffer_free(vbuf);
247  }
248  return 0;
249 }
250 
251 
252 
253 
254 
255 
256 
257 int _handleXmlEnter(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
258 {
259  const char *path;
260  GWEN_XMLNODE *n;
261  int rv;
262 
263  path=GWEN_XMLNode_GetProperty(xmlNode, "path", NULL);
264  if (path==NULL) {
265  DBG_ERROR(GWEN_LOGDOMAIN, "Missing path in \"EnterPath\"");
266  return GWEN_ERROR_INVALID;
267  }
268 
269  n=GWEN_XMLNode_GetNodeByXPath(ctx->currentDocNode, path, GWEN_PATH_FLAGS_PATHMUSTEXIST);
270  if (n==NULL) {
271  DBG_ERROR(GWEN_LOGDOMAIN, "Path \"%s\" does not exist", path);
272  return GWEN_ERROR_INVALID;
273  }
274 
275  /* enter given document node */
277 
278  rv=GWEN_Xml2Db_Context_HandleChildren(ctx, xmlNode);
279  if (rv<0) {
280  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
281  return rv;
282  }
283 
284  /* leave given document node, re-select previously active one, thus restoring status from the beginning */
286  return 0;
287 }
288 
289 
290 
291 int _handleXmlForEvery(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
292 {
293  const char *path;
294  GWEN_XMLNODE *n;
295  int rv;
296 
297  path=GWEN_XMLNode_GetProperty(xmlNode, "name", NULL);
298  if (path==NULL) {
299  DBG_ERROR(GWEN_LOGDOMAIN, "Missing name in \"ForEvery\"");
300  return GWEN_ERROR_INVALID;
301  }
302 
303  n=GWEN_XMLNode_FindFirstTag(ctx->currentDocNode, path, NULL, NULL);
304  if (n==NULL) {
305  DBG_ERROR(GWEN_LOGDOMAIN, "Path \"%s\" not found", path);
306  /* GWEN_XMLNode_Dump(ctx->currentDocNode, 2); */
307  }
308  while (n) {
309 
310  /* enter given document node */
312 
313  /* handle all children of this parser XML node with the current document node */
314  rv=GWEN_Xml2Db_Context_HandleChildren(ctx, xmlNode);
315 
316  /* leave given document node, re-select previously active one, thus restoring status from the beginning */
318 
319  if (rv<0) {
320  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
321  return rv;
322  }
323 
324  n=GWEN_XMLNode_FindNextTag(n, path, NULL, NULL);
325  }
326 
327  return 0;
328 }
329 
330 
331 
332 int _handleDbCreateAndEnterGroup(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
333 {
334  const char *name;
335  GWEN_DB_NODE *dbLast;
336  int rv;
337 
338  name=GWEN_XMLNode_GetProperty(xmlNode, "name", NULL);
339  if (!(name && *name)) {
340  DBG_ERROR(GWEN_LOGDOMAIN, "Missing or empty name in \"CreateAnEnterDbGroup\"");
341  return GWEN_ERROR_INVALID;
342  }
343 
344  /* push group */
345  dbLast=ctx->currentDbGroup;
346 
347  /* create group */
348  ctx->currentDbGroup=GWEN_DB_GetGroup(dbLast, GWEN_PATH_FLAGS_CREATE_GROUP, name);
349 
350  /* handle children (nothing special here) */
351  rv=GWEN_Xml2Db_Context_HandleChildren(ctx, xmlNode);
352 
353  /* pop group */
354  ctx->currentDbGroup=dbLast;
355 
356  if (rv<0) {
357  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
358  return rv;
359  }
360 
361  return 0;
362 }
363 
364 
365 
366 int _handleDbCreateAndEnterTempGroup(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
367 {
368  const char *name;
369  GWEN_DB_NODE *dbLast;
370  int rv;
371 
372  name=GWEN_XMLNode_GetProperty(xmlNode, "name", NULL);
373  if (!(name && *name)) {
374  DBG_ERROR(GWEN_LOGDOMAIN, "Missing or empty name in \"CreateAnEnterTempDbGroup\"");
375  return GWEN_ERROR_INVALID;
376  }
377 
378  /* push group */
379  dbLast=ctx->currentTempDbGroup;
380 
381  /* create group */
382  ctx->currentTempDbGroup=GWEN_DB_GetGroup(dbLast, GWEN_PATH_FLAGS_CREATE_GROUP, name);
383  assert(ctx->currentTempDbGroup);
384 
385  /* handle children (nothing special here) */
386  rv=GWEN_Xml2Db_Context_HandleChildren(ctx, xmlNode);
387 
388  /* delete temp group */
389  GWEN_DB_UnlinkGroup(ctx->currentTempDbGroup);
390  GWEN_DB_Group_free(ctx->currentTempDbGroup);
391 
392  /* pop group */
393  ctx->currentTempDbGroup=dbLast;
394 
395  if (rv<0) {
396  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
397  return rv;
398  }
399 
400  return 0;
401 }
402 
403 
404 
405 int _handleDbSetCharValue_internal(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode,
406  GWEN_DB_NODE *dbCurrent)
407 {
408  const char *name;
409  const char *value;
410 
411  name=GWEN_XMLNode_GetProperty(xmlNode, "name", NULL);
412  if (!(name && *name)) {
413  DBG_ERROR(GWEN_LOGDOMAIN, "Missing or empty name in \"SetCharValue\"");
414  return GWEN_ERROR_INVALID;
415  }
416 
417  value=GWEN_XMLNode_GetProperty(xmlNode, "value", NULL);
418  if (value) {
419  GWEN_BUFFER *dbuf;
420  int rv;
421 
422  dbuf=GWEN_Buffer_new(0, 256, 0, 1);
423  rv=GWEN_DB_ReplaceVars(ctx->currentTempDbGroup, value, dbuf);
424  if (rv<0) {
425  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
426  GWEN_Buffer_free(dbuf);
427  return rv;
428  }
429  _convertAndSetCharValue(ctx, xmlNode, dbCurrent, GWEN_Buffer_GetStart(dbuf));
430  GWEN_Buffer_free(dbuf);
431  }
432  else {
433  const char *path;
434 
435  path=GWEN_XMLNode_GetProperty(xmlNode, "path", NULL);
436  if (!(path && *path)) {
437  DBG_ERROR(GWEN_LOGDOMAIN, "Missing or empty path in \"SetCharValue\"");
438  return GWEN_ERROR_INVALID;
439  }
440 
441  value=_getCharValueByPath(ctx->currentDocNode, path, NULL);
442  if (value && *value) {
443  _convertAndSetCharValue(ctx, xmlNode, dbCurrent, value);
444  }
445 #if 0
446  else {
447  GWEN_BUFFER *tbuf;
448 
449  tbuf=GWEN_Buffer_new(0, 256, 0, 1);
450 
451  GWEN_XMLNode_GetXPath(NULL, ctx->currentDocNode, tbuf);
452 
453  DBG_ERROR(GWEN_LOGDOMAIN, "No value in path \"%s\" (%s)", path, GWEN_Buffer_GetStart(tbuf));
454  GWEN_Buffer_free(tbuf);
455 
456  /* GWEN_XMLNode_Dump(ctx->currentDocNode, 2); */
457  }
458 #endif
459  }
460 
461  return 0;
462 }
463 
464 
465 
466 int _handleDbSetCharValue(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
467 {
468  return _handleDbSetCharValue_internal(ctx, xmlNode, ctx->currentDbGroup);
469 }
470 
471 
472 
473 int _handleDbSetTempCharValue(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
474 {
475  return _handleDbSetCharValue_internal(ctx, xmlNode, ctx->currentTempDbGroup);
476 }
477 
478 
479 
480 int _handleXmlIfCharDataMatches(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
481 {
482  const char *pattern;
483  const char *path;
484  const char *value;
485 
486  path=GWEN_XMLNode_GetProperty(xmlNode, "path", NULL);
487  if (!(path && *path)) {
488  DBG_ERROR(GWEN_LOGDOMAIN, "Missing or empty path in \"IfCharDataMatches\"");
489  return GWEN_ERROR_INVALID;
490  }
491 
492  pattern=GWEN_XMLNode_GetProperty(xmlNode, "pattern", NULL);
493  if (!(pattern && *pattern)) {
494  DBG_ERROR(GWEN_LOGDOMAIN, "Missing or empty pattern in \"IfCharDataMatches\"");
495  return GWEN_ERROR_INVALID;
496  }
497 
498  value=_getCharValueByPath(ctx->currentDocNode, path, NULL);
499  if (value) {
500  if (-1!=GWEN_Text_ComparePattern(value, pattern, 0)) {
501  int rv;
502 
503  /* pattern matches, handle children */
504  rv=GWEN_Xml2Db_Context_HandleChildren(ctx, xmlNode);
505  if (rv<0) {
506  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
507  return rv;
508  }
509  }
510  }
511 
512  return 0;
513 }
514 
515 
516 
517 int _handleXmlIfNotCharDataMatches(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
518 {
519  const char *pattern;
520  const char *path;
521  const char *value;
522 
523  path=GWEN_XMLNode_GetProperty(xmlNode, "path", NULL);
524  if (!(path && *path)) {
525  DBG_ERROR(GWEN_LOGDOMAIN, "Missing or empty path in \"IfNotCharDataMatches\"");
526  return GWEN_ERROR_INVALID;
527  }
528 
529  pattern=GWEN_XMLNode_GetProperty(xmlNode, "pattern", NULL);
530  if (!(pattern && *pattern)) {
531  DBG_ERROR(GWEN_LOGDOMAIN, "Missing or empty pattern in \"IfNotCharDataMatches\"");
532  return GWEN_ERROR_INVALID;
533  }
534 
535  value=_getCharValueByPath(ctx->currentDocNode, path, NULL);
536  if (value) {
537  if (-1==GWEN_Text_ComparePattern(value, pattern, 0)) {
538  int rv;
539 
540  /* pattern doesnt match, handle children */
541  rv=GWEN_Xml2Db_Context_HandleChildren(ctx, xmlNode);
542  if (rv<0) {
543  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
544  return rv;
545  }
546  }
547  }
548 
549  return 0;
550 }
551 
552 
553 
554 int _handleXmlIfHasCharData(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
555 {
556  const char *path;
557  const char *value;
558 
559  path=GWEN_XMLNode_GetProperty(xmlNode, "path", NULL);
560  if (!(path && *path)) {
561  DBG_ERROR(GWEN_LOGDOMAIN, "Missing or empty path in \"IfCharDataMatches\"");
562  return GWEN_ERROR_INVALID;
563  }
564 
565  value=_getCharValueByPath(ctx->currentDocNode, path, NULL);
566  if (value && *value) {
567  int rv;
568 
569  /* there is a value, handle children */
570  rv=GWEN_Xml2Db_Context_HandleChildren(ctx, xmlNode);
571  if (rv<0) {
572  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
573  return rv;
574  }
575  }
576  else {
577  DBG_INFO(GWEN_LOGDOMAIN, "No value for path \"%s\"", path);
578  }
579 
580  return 0;
581 }
582 
583 
584 
585 int _handleXmlIfNotHasCharData(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
586 {
587  const char *path;
588  const char *value;
589 
590  path=GWEN_XMLNode_GetProperty(xmlNode, "path", NULL);
591  if (!(path && *path)) {
592  DBG_ERROR(GWEN_LOGDOMAIN, "Missing or empty path in \"IfNotCharDataMatches\"");
593  return GWEN_ERROR_INVALID;
594  }
595 
596  value=_getCharValueByPath(ctx->currentDocNode, path, NULL);
597  if (!(value && *value)) {
598  int rv;
599 
600  /* there is a value, handle children */
601  rv=GWEN_Xml2Db_Context_HandleChildren(ctx, xmlNode);
602  if (rv<0) {
603  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
604  return rv;
605  }
606  }
607 
608  return 0;
609 }
610 
611 
612 
613 int _handleXmlIfPathExists(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
614 {
615  const char *path;
616 
617  path=GWEN_XMLNode_GetProperty(xmlNode, "path", NULL);
618  if (!(path && *path)) {
619  DBG_ERROR(GWEN_LOGDOMAIN, "Missing or empty path in \"IfPathExists\"");
620  return GWEN_ERROR_INVALID;
621  }
622 
623  if (GWEN_XMLNode_GetNodeByXPath(ctx->currentDocNode, path, GWEN_PATH_FLAGS_PATHMUSTEXIST)) {
624  int rv;
625 
626  /* path exists, handle children */
627  rv=GWEN_Xml2Db_Context_HandleChildren(ctx, xmlNode);
628  if (rv<0) {
629  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
630  return rv;
631  }
632  }
633  else {
634  DBG_INFO(GWEN_LOGDOMAIN, "Path \"%s\" does not exist", path);
635  }
636 
637  return 0;
638 }
639 
640 
641 
642 int _handleXmlIfNotPathExists(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
643 {
644  const char *path;
645 
646  path=GWEN_XMLNode_GetProperty(xmlNode, "path", NULL);
647  if (!(path && *path)) {
648  DBG_ERROR(GWEN_LOGDOMAIN, "Missing or empty path in \"IfNotPathExists\"");
649  return GWEN_ERROR_INVALID;
650  }
651 
652  if (NULL==GWEN_XMLNode_GetNodeByXPath(ctx->currentDocNode, path, GWEN_PATH_FLAGS_PATHMUSTEXIST)) {
653  int rv;
654 
655  /* path does not exist, handle children */
656  rv=GWEN_Xml2Db_Context_HandleChildren(ctx, xmlNode);
657  if (rv<0) {
658  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
659  return rv;
660  }
661  }
662  else {
663  DBG_INFO(GWEN_LOGDOMAIN, "Path \"%s\" exists", path);
664  }
665 
666  return 0;
667 }
668 
669 
670 
671 int _handleChildren_toDb(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
672 {
673  GWEN_XMLNODE *n;
674 
675  n=GWEN_XMLNode_GetFirstTag(xmlNode);
676  while (n) {
677  const char *name;
678 
679  name=GWEN_XMLNode_GetData(n);
680  if (name && *name) {
681  int rv;
682 
683  DBG_INFO(GWEN_LOGDOMAIN, "Handling element \"%s\"", name);
684  if (strcasecmp(name, "XmlEnter")==0)
685  rv=_handleXmlEnter(ctx, n);
686  else if (strcasecmp(name, "XmlForEvery")==0)
687  rv=_handleXmlForEvery(ctx, n);
688  else if (strcasecmp(name, "DbCreateAndEnterGroup")==0)
689  rv=_handleDbCreateAndEnterGroup(ctx, n);
690  else if (strcasecmp(name, "DbCreateAndEnterTempGroup")==0)
692  else if (strcasecmp(name, "DbSetCharValue")==0)
693  rv=_handleDbSetCharValue(ctx, n);
694  else if (strcasecmp(name, "DbSetTempCharValue")==0)
695  rv=_handleDbSetTempCharValue(ctx, n);
696  else if (strcasecmp(name, "XmlIfCharDataMatches")==0)
697  rv=_handleXmlIfCharDataMatches(ctx, n);
698  else if (strcasecmp(name, "XmlIfNotCharDataMatches")==0)
700  else if (strcasecmp(name, "XmlIfHasCharData")==0)
701  rv=_handleXmlIfHasCharData(ctx, n);
702  else if (strcasecmp(name, "XmlIfNotHasCharData")==0)
703  rv=_handleXmlIfNotHasCharData(ctx, n);
704  else if (strcasecmp(name, "XmlIfPathExists")==0)
705  rv=_handleXmlIfPathExists(ctx, n);
706  else if (strcasecmp(name, "XmlIfNotPathExists")==0)
707  rv=_handleXmlIfNotPathExists(ctx, n);
708  else {
709  DBG_ERROR(GWEN_LOGDOMAIN, "Unknown element \"%s\", aborting", name);
710  return GWEN_ERROR_INVALID;
711  }
712  if (rv<0) {
713  DBG_ERROR(GWEN_LOGDOMAIN, "Error in element \"%s\", aborting", name);
714  return rv;
715  }
716  }
717 
719  }
720 
721  return 0;
722 }
723 
724 
725 
726 
727 
GWEN_XML2DB_CONTEXT * GWEN_Xml2Db_Context_new(GWEN_XMLNODE *documentRoot, GWEN_DB_NODE *dbRoot)
Definition: xml2db.c:47
int GWEN_DB_ReplaceVars(GWEN_DB_NODE *db, const char *s, GWEN_BUFFER *dbuf)
Definition: db.c:1949
static int _handleXmlEnter(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
Definition: xml2db_todb.c:257
char * GWEN_Buffer_GetStart(const GWEN_BUFFER *bf)
Definition: buffer.c:235
void GWEN_Text_CondenseBuffer(GWEN_BUFFER *buf)
Definition: text.c:1620
static int _handleDbSetCharValue_internal(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode, GWEN_DB_NODE *dbCurrent)
Definition: xml2db_todb.c:405
static int _handleDbCreateAndEnterGroup(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
Definition: xml2db_todb.c:332
GWEN_DATE * GWEN_Date_fromStringWithTemplate(const char *s, const char *tmpl)
Definition: gwendate.c:377
static int _handleXmlIfCharDataMatches(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
Definition: xml2db_todb.c:480
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
void GWEN_Xml2Db_Context_EnterDocNode(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
Definition: xml2db.c:81
int GWEN_Xml2Db(GWEN_XMLNODE *xmlNodeDocument, GWEN_XMLNODE *xmlNodeSchema, GWEN_DB_NODE *dbDestination)
Definition: xml2db_todb.c:79
#define NULL
Definition: binreloc.c:300
static int _handleXmlForEvery(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
Definition: xml2db_todb.c:291
#define GWEN_PATH_FLAGS_CREATE_GROUP
Definition: path.h:96
int GWEN_Xml2Db_Context_HandleChildren(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
Definition: xml2db.c:109
static int _handleChildren_toDb(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
Definition: xml2db_todb.c:671
#define GWEN_LOGDOMAIN
Definition: logger.h:35
static int _handleXmlIfNotPathExists(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
Definition: xml2db_todb.c:642
GWEN_BUFFER * GWEN_Buffer_new(char *buffer, uint32_t size, uint32_t used, int take)
Definition: buffer.c:42
static int _handleDbSetCharValue(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
Definition: xml2db_todb.c:466
GWEN_XMLNODE * GWEN_XMLNode_FindFirstTag(const GWEN_XMLNODE *n, const char *tname, const char *pname, const char *pvalue)
Definition: xml.c:736
static int _handleXmlIfPathExists(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
Definition: xml2db_todb.c:613
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:68
GWEN_XMLNODE * GWEN_XMLNode_GetNextTag(const GWEN_XMLNODE *n)
Definition: xml.c:672
static int _convertAndSetCharValue(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode, GWEN_DB_NODE *dbCurrent, const char *value)
static int _handleDbSetTempCharValue(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
Definition: xml2db_todb.c:473
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:394
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:89
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
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:92
#define DBG_ERROR(dbg_logger, format, args...)
Definition: debug.h:97
GWEN_XMLNODE * GWEN_XMLNode_GetFirstTag(const GWEN_XMLNODE *n)
Definition: xml.c:665
static int _handleXmlIfNotHasCharData(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
Definition: xml2db_todb.c:585
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
#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
static int _handleXmlIfHasCharData(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
Definition: xml2db_todb.c:554
const char * GWEN_XMLNode_GetCharValueByPath(GWEN_XMLNODE *n, const char *name, const char *defValue)
Definition: xml.c:941
static int _handleXmlIfNotCharDataMatches(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
Definition: xml2db_todb.c:517
static const char * _getCharValueByPath(GWEN_XMLNODE *xmlNode, const char *path, const char *defValue)
Definition: xml2db_todb.c:103
struct GWEN__XMLNODE GWEN_XMLNODE
Definition: xml.h:149
#define GWEN_UNUSED
int GWEN_Buffer_AppendString(GWEN_BUFFER *bf, const char *buffer)
Definition: buffer.c:989
static int _handleDbCreateAndEnterTempGroup(GWEN_XML2DB_CONTEXT *ctx, GWEN_XMLNODE *xmlNode)
Definition: xml2db_todb.c:366
#define GWEN_DB_FLAGS_DEFAULT
Definition: db.h:168
struct GWEN_DATE GWEN_DATE
Definition: gwendate.h:34