xml2ns0.c 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. /*
  2. * xml2ns0.c
  3. *
  4. * Created on: 21.04.2014
  5. * Author: mrt
  6. */
  7. #include <expat.h>
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <string.h> // strlen
  11. #include "opcua.h"
  12. typedef char const * const XML_Attr_t;
  13. typedef char const * cstring_t;
  14. struct XML_Stack;
  15. typedef UA_Int32 (*XML_decoder)(struct XML_Stack* s, XML_Attr_t* attr, void* dst);
  16. typedef struct XML_child {
  17. cstring_t name;
  18. UA_Int32 type;
  19. XML_decoder handler;
  20. void* obj;
  21. } XML_child_t;
  22. typedef struct XML_Parent {
  23. cstring_t name;
  24. int textAttribIdx; // -1 - not set
  25. cstring_t textAttrib;
  26. int len; // -1 - empty set
  27. XML_child_t children[20];
  28. } XML_Parent_t;
  29. typedef struct XML_Stack {
  30. int depth;
  31. XML_Parent_t parent[10];
  32. } XML_Stack_t;
  33. void XML_Stack_init(XML_Stack_t* p, cstring_t name) {
  34. unsigned int i,j;
  35. p->depth = 0;
  36. for (i=0;i<10;i++) {
  37. p->parent[i].name = UA_NULL;
  38. p->parent[i].len = 0;
  39. p->parent[i].textAttrib = UA_NULL;
  40. p->parent[i].textAttribIdx = -1;
  41. for (j=0;j<20;j++) {
  42. p->parent[i].children[j].name = UA_NULL;
  43. p->parent[i].children[j].handler = UA_NULL;
  44. p->parent[i].children[j].type = UA_INVALIDTYPE;
  45. p->parent[i].children[j].obj = UA_NULL;
  46. }
  47. }
  48. p->parent[0].name = name;
  49. }
  50. // FIXME: we might want to calculate textAttribIdx
  51. void XML_Stack_handleTextAs(XML_Stack_t* p,cstring_t textAttrib, unsigned int textAttribIdx) {
  52. p->parent[p->depth].textAttrib = textAttrib;
  53. p->parent[p->depth].textAttribIdx = textAttribIdx;
  54. }
  55. void XML_Stack_addChildHandler(XML_Stack_t* p,cstring_t name,XML_decoder handler, UA_Int32 type, void* dst) {
  56. unsigned int len = p->parent[p->depth].len;
  57. p->parent[p->depth].children[len].name = name;
  58. p->parent[p->depth].children[len].handler = handler;
  59. p->parent[p->depth].children[len].type = type;
  60. p->parent[p->depth].children[len].obj = dst;
  61. p->parent[p->depth].len++;
  62. }
  63. UA_Int32 UA_NodeId_copycstring(cstring_t src,UA_NodeId* dst) {
  64. dst->encodingByte = UA_NODEIDTYPE_FOURBYTE;
  65. dst->namespace = 0;
  66. // FIXME: assumes i=nnnn, does not care for aliases as of now
  67. dst->identifier.numeric = atoi(&src[2]);
  68. return UA_SUCCESS;
  69. }
  70. typedef struct T_UA_NodeSet { int dummy; } UA_NodeSet;
  71. UA_Int32 UA_Array_decodeXML(XML_Stack_t* s, XML_Attr_t* attr, void* dst) {
  72. UA_UInt32 i;
  73. return UA_SUCCESS;
  74. }
  75. UA_Int32 UA_Int32_decodeXML(XML_Stack_t* s, XML_Attr_t* attr, UA_Int32* dst) {
  76. UA_UInt32 i;
  77. if (dst == UA_NULL) { UA_[UA_INT32].new((void**) &dst); }
  78. return UA_SUCCESS;
  79. }
  80. UA_Int32 UA_String_decodeXML(XML_Stack_t* s, XML_Attr_t* attr, UA_String* dst) {
  81. UA_UInt32 i;
  82. if (dst == UA_NULL) { UA_[UA_STRING].new((void**) &dst); }
  83. if (s->parent[s->depth].len == 0 ) {
  84. XML_Stack_addChildHandler(s,"Data",(XML_decoder)UA_Array_decodeXML, UA_BYTE, &(dst->data));
  85. XML_Stack_addChildHandler(s,"Length",(XML_decoder)UA_Int32_decodeXML, UA_INT32, &(dst->length));
  86. XML_Stack_handleTextAs(s,"Data",0);
  87. }
  88. // set attributes
  89. for (i = 0; attr[i]; i += 2) {
  90. if (0==strncmp("Data",attr[i],strlen("Data"))) {
  91. UA_String_copycstring(attr[i+1],dst);
  92. } else {
  93. perror("Unknown attribute");
  94. }
  95. }
  96. return UA_SUCCESS;
  97. }
  98. UA_Int32 UA_LocalizedText_decodeXML(XML_Stack_t* s, XML_Attr_t* attr, UA_LocalizedText* dst) {
  99. UA_UInt32 i;
  100. // create a new object if called with UA_NULL
  101. if (dst == UA_NULL) { UA_[UA_LOCALIZEDTEXT].new((void**) &dst); }
  102. if (s->parent[s->depth].len == 0 ) {
  103. XML_Stack_addChildHandler(s,"Text",(XML_decoder)UA_String_decodeXML, UA_STRING, &(dst->text));
  104. XML_Stack_addChildHandler(s,"Locale",(XML_decoder)UA_String_decodeXML, UA_STRING, &(dst->locale));
  105. XML_Stack_handleTextAs(s,"Data",0);
  106. }
  107. return UA_SUCCESS;
  108. }
  109. UA_Int32 UA_DataTypeNode_decodeXML(XML_Stack_t* s, XML_Attr_t* attr, UA_DataTypeNode* dst) {
  110. UA_UInt32 i;
  111. // create a new object if called with UA_NULL
  112. if (dst == UA_NULL) { UA_[UA_DATATYPENODE].new((void**) &dst); }
  113. // add the handlers for the child objects
  114. if (s->parent[s->depth].len == 0 ) {
  115. XML_Stack_addChildHandler(s,"DisplayName",(XML_decoder)UA_LocalizedText_decodeXML, UA_LOCALIZEDTEXT, &(dst->displayName));
  116. XML_Stack_addChildHandler(s,"Description",(XML_decoder)UA_LocalizedText_decodeXML, UA_LOCALIZEDTEXT, &(dst->description));
  117. }
  118. // set missing but implicit attributes
  119. dst->nodeClass = UA_NODECLASS_DATATYPE;
  120. // set attributes
  121. for (i = 0; attr[i]; i += 2) {
  122. if (0==strncmp("NodeId",attr[i],strlen("NodeId"))) {
  123. UA_NodeId_copycstring(attr[i+1],&(dst->nodeId));
  124. } else if (0==strncmp("BrowseName",attr[i],strlen("BrowseName"))) {
  125. UA_String_copycstring(attr[i+1],&(dst->browseName.name));
  126. dst->browseName.namespaceIndex = 0;
  127. // } else if (0==strncmp("DisplayName",attr[i],strlen("DisplayName"))) {
  128. // UA_String_copycstring(attr[i+1],&(dst->displayName.text));
  129. // dst->displayName.encodingMask = UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_TEXT;
  130. // } else if (0==strncmp("Description",attr[i],strlen("Description"))) {
  131. // UA_String_copycstring(attr[i+1],&(dst->description.text));
  132. // dst->description.encodingMask = UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_TEXT;
  133. } else {
  134. perror("Unknown attribute");
  135. }
  136. }
  137. return UA_SUCCESS;
  138. }
  139. UA_Int32 UA_NodeSet_decodeXML(XML_Stack_t* s, XML_Attr_t* attr, UA_NodeSet* dst) {
  140. if (s->parent[s->depth].len == 0 ) {
  141. XML_Stack_addChildHandler(s,"UADataType",(XML_decoder)UA_DataTypeNode_decodeXML, UA_DATATYPENODE, UA_NULL);
  142. }
  143. return UA_SUCCESS;
  144. }
  145. void startElement(void * data, const char *el, const char **attr) {
  146. XML_Stack_t* p = (XML_Stack_t*) data;
  147. int i, j;
  148. // scan expected children
  149. XML_Parent_t* cp = &p->parent[p->depth];
  150. for (i = 0; i < cp->len; i++) {
  151. if (0 == strncmp(cp->children[i].name,el,strlen(cp->children[i].name))) {
  152. printf("processing child ");
  153. for (j=0;j<=p->depth;j++) {
  154. printf("%s.",p->parent[j].name);
  155. }
  156. printf("%s\n",el);
  157. p->depth++;
  158. p->parent[p->depth].name = el;
  159. p->parent[p->depth].len = 0;
  160. p->parent[p->depth].textAttribIdx = -1;
  161. // finally call the handler and return
  162. cp->children[i].handler(data,attr,cp->children[i].obj);
  163. return;
  164. }
  165. }
  166. // if we come here we rejected the processing of el
  167. printf("rejected processing of unexpected child ");
  168. for (i=0;i<=p->depth;i++) {
  169. printf("%s.",p->parent[i].name);
  170. }
  171. printf("%s\n",el);
  172. p->depth++;
  173. p->parent[p->depth].name = el;
  174. // this should be sufficient to reject the children as well
  175. p->parent[p->depth].len = 0;
  176. } /* End of start handler */
  177. UA_Int32 XML_isSpace(cstring_t s, int len) {
  178. UA_Int32 retval = UA_TRUE;
  179. int i;
  180. for (i=0; i<len; i++) {
  181. if (! isspace(s[i])) {
  182. return UA_FALSE;
  183. }
  184. }
  185. return UA_TRUE;
  186. }
  187. void handleText(void * data, const char *s, int len) {
  188. XML_Stack_t* p = (XML_Stack_t*) data;
  189. int j, i;
  190. if (len > 0 && ! XML_isSpace(s,len)) {
  191. XML_Parent_t* cp = &(p->parent[p->depth]);
  192. if (cp->textAttribIdx >= 0) {
  193. int childIdx = cp->textAttribIdx;
  194. char* buf; // need to copy s to add a 0 as terminator to string
  195. UA_alloc((void**)&buf,len+1);
  196. strncpy(buf,s,len);
  197. buf[len+1] = 0;
  198. XML_Attr_t attr[3] = { cp->textAttrib, buf, UA_NULL };
  199. cp->children[childIdx].handler(p,attr,cp->children[childIdx].obj);
  200. UA_free(buf);
  201. }
  202. }
  203. } /* End of text handler */
  204. void endElement(void *data, const char *el) {
  205. XML_Stack_t* p = (XML_Stack_t*) data;
  206. p->depth--;
  207. } /* End of end handler */
  208. int main()
  209. {
  210. char buf[1024];
  211. int len; /* len is the number of bytes in the current bufferful of data */
  212. int done;
  213. XML_Stack_t p;
  214. XML_Stack_init(&p, "ROOT");
  215. XML_Stack_addChildHandler(&p,"UANodeSet", (XML_decoder) UA_NodeSet_decodeXML, UA_INVALIDTYPE, UA_NULL);
  216. XML_Parser parser = XML_ParserCreate(NULL);
  217. XML_SetUserData(parser, &p);
  218. XML_SetElementHandler(parser, startElement, endElement);
  219. XML_SetCharacterDataHandler(parser, handleText);
  220. while ((len = read(0,buf,1024)) > 0) {
  221. if (!XML_Parse(parser, buf, len, (len<1024))) {
  222. return 1;
  223. }
  224. }
  225. XML_ParserFree(parser);
  226. return 0;
  227. }