|
WizardsToolkit
1.0.7
|
00001 /* 00002 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00003 % % 00004 % % 00005 % % 00006 % X X M M L % 00007 % X X MM MM L % 00008 % X M M M L % 00009 % X X M M L % 00010 % X X M M LLLLL % 00011 % % 00012 % TTTTT RRRR EEEEE EEEEE % 00013 % T R R E E % 00014 % T RRRR EEE EEE % 00015 % T R R E E % 00016 % T R R EEEEE EEEEE % 00017 % % 00018 % % 00019 % XML Tree Methods % 00020 % % 00021 % Software Design % 00022 % John Cristy % 00023 % December 2004 % 00024 % % 00025 % % 00026 % Copyright 1999-2011 ImageMagick Studio LLC, a non-profit organization % 00027 % dedicated to making software imaging solutions freely available. % 00028 % % 00029 % You may not use this file except in compliance with the License. You may % 00030 % obtain a copy of the License at % 00031 % % 00032 % http://www.wizards-toolkit.org/script/license.php % 00033 % % 00034 % Unless required by applicable law or agreed to in writing, software % 00035 % distributed under the License is distributed on an "AS IS" BASIS, % 00036 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. % 00037 % See the License for the specific language governing permissions and % 00038 % limitations under the License. % 00039 % % 00040 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00041 % 00042 % This module implements the standard handy xml-tree methods for storing and 00043 % retrieving nodes and attributes from an XML string. 00044 % 00045 */ 00046 00047 /* 00048 Include declarations. 00049 */ 00050 #include "wizard/studio.h" 00051 #include "wizard/blob.h" 00052 #include "wizard/exception.h" 00053 #include "wizard/exception-private.h" 00054 #include "wizard/log.h" 00055 #include "wizard/memory_.h" 00056 #include "wizard/semaphore.h" 00057 #include "wizard/splay-tree.h" 00058 #include "wizard/string_.h" 00059 #include "wizard/string-private.h" 00060 #include "wizard/xml-tree.h" 00061 #include "wizard/utility.h" 00062 00063 /* 00064 Define declarations. 00065 */ 00066 #define NumberPredefinedEntities 10 00067 #define XMLWhitespace "\t\r\n " 00068 00069 /* 00070 Typedef declarations. 00071 */ 00072 struct _XMLTreeInfo 00073 { 00074 char 00075 *tag, 00076 **attributes, 00077 *content; 00078 00079 size_t 00080 offset; 00081 00082 XMLTreeInfo 00083 *parent, 00084 *next, 00085 *sibling, 00086 *ordered, 00087 *child; 00088 00089 WizardBooleanType 00090 debug; 00091 00092 SemaphoreInfo 00093 *semaphore; 00094 00095 size_t 00096 signature; 00097 }; 00098 00099 typedef struct _XMLTreeRoot 00100 XMLTreeRoot; 00101 00102 struct _XMLTreeRoot 00103 { 00104 struct _XMLTreeInfo 00105 root; 00106 00107 XMLTreeInfo 00108 *node; 00109 00110 WizardBooleanType 00111 standalone; 00112 00113 char 00114 ***processing_instructions, 00115 **entities, 00116 ***attributes; 00117 00118 WizardBooleanType 00119 debug; 00120 00121 SemaphoreInfo 00122 *semaphore; 00123 00124 size_t 00125 signature; 00126 }; 00127 00128 /* 00129 Global declarations. 00130 */ 00131 static char 00132 *sentinel[] = { (char *) NULL }; 00133 00134 /* 00135 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00136 % % 00137 % % 00138 % % 00139 % A d d C h i l d T o X M L T r e e % 00140 % % 00141 % % 00142 % % 00143 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00144 % 00145 % AddChildToXMLTree() adds a child tag at an offset relative to the start of 00146 % the parent tag's character content. Return the child tag. 00147 % 00148 % The format of the AddChildToXMLTree method is: 00149 % 00150 % XMLTreeInfo *AddChildToXMLTree(XMLTreeInfo *xml_info,const char *tag, 00151 % const size_t offset) 00152 % 00153 % A description of each parameter follows: 00154 % 00155 % o xml_info: the xml info. 00156 % 00157 % o tag: the tag. 00158 % 00159 % o offset: the tag offset. 00160 % 00161 */ 00162 WizardExport XMLTreeInfo *AddChildToXMLTree(XMLTreeInfo *xml_info, 00163 const char *tag,const size_t offset) 00164 { 00165 XMLTreeInfo 00166 *child; 00167 00168 if (xml_info == (XMLTreeInfo *) NULL) 00169 return((XMLTreeInfo *) NULL); 00170 child=(XMLTreeInfo *) AcquireWizardMemory(sizeof(*child)); 00171 if (child == (XMLTreeInfo *) NULL) 00172 return((XMLTreeInfo *) NULL); 00173 (void) ResetWizardMemory(child,0,sizeof(*child)); 00174 child->tag=ConstantString(tag); 00175 child->attributes=sentinel; 00176 child->content=ConstantString(""); 00177 child->debug=IsEventLogging(); 00178 child->signature=WizardSignature; 00179 return(InsertTagIntoXMLTree(xml_info,child,offset)); 00180 } 00181 00182 /* 00183 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00184 % % 00185 % % 00186 % % 00187 % A d d P a t h T o X M L T r e e % 00188 % % 00189 % % 00190 % % 00191 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00192 % 00193 % AddPathToXMLTree() adds a child tag at an offset relative to the start of 00194 % the parent tag's character content. This method returns the child tag. 00195 % 00196 % The format of the AddPathToXMLTree method is: 00197 % 00198 % XMLTreeInfo *AddPathToXMLTree(XMLTreeInfo *xml_info,const char *path, 00199 % const size_t offset) 00200 % 00201 % A description of each parameter follows: 00202 % 00203 % o xml_info: the xml info. 00204 % 00205 % o path: the path. 00206 % 00207 % o offset: the tag offset. 00208 % 00209 */ 00210 WizardExport XMLTreeInfo *AddPathToXMLTree(XMLTreeInfo *xml_info, 00211 const char *path,const size_t offset) 00212 { 00213 char 00214 **components, 00215 subnode[MaxTextExtent], 00216 tag[MaxTextExtent]; 00217 00218 ssize_t 00219 j; 00220 00221 register ssize_t 00222 i; 00223 00224 XMLTreeInfo 00225 *child, 00226 *node; 00227 00228 size_t 00229 number_components; 00230 00231 WizardAssert(ResourceDomain,xml_info != (XMLTreeInfo *) NULL); 00232 WizardAssert(ResourceDomain,(xml_info->signature == WizardSignature) || 00233 (((XMLTreeRoot *) xml_info)->signature == WizardSignature)); 00234 (void) LogWizardEvent(TraceEvent,GetWizardModule(),"..."); 00235 node=xml_info; 00236 components=GetPathComponents(path,&number_components); 00237 if (components == (char **) NULL) 00238 return((XMLTreeInfo *) NULL); 00239 for (i=0; i < (ssize_t) number_components; i++) 00240 { 00241 GetPathComponent(components[i],SubnodePath,subnode); 00242 GetPathComponent(components[i],CanonicalPath,tag); 00243 child=GetXMLTreeChild(node,tag); 00244 if (child == (XMLTreeInfo *) NULL) 00245 child=AddChildToXMLTree(node,tag,offset); 00246 node=child; 00247 if (node == (XMLTreeInfo *) NULL) 00248 break; 00249 for (j=StringToLong(subnode)-1; j > 0; j--) 00250 { 00251 node=GetXMLTreeOrdered(node); 00252 if (node == (XMLTreeInfo *) NULL) 00253 break; 00254 } 00255 if (node == (XMLTreeInfo *) NULL) 00256 break; 00257 components[i]=DestroyString(components[i]); 00258 } 00259 for ( ; i < (ssize_t) number_components; i++) 00260 components[i]=DestroyString(components[i]); 00261 components=(char **) RelinquishWizardMemory(components); 00262 return(node); 00263 } 00264 00265 /* 00266 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00267 % % 00268 % % 00269 % % 00270 % C a n o n i c a l X M L C o n t e n t % 00271 % % 00272 % % 00273 % % 00274 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00275 % 00276 % CanonicalXMLContent() converts text to canonical XML content by converting 00277 % to UTF-8, substituting predefined entities, wrapping as CDATA, or encoding 00278 % as base-64 as required. 00279 % 00280 % The format of the CanonicalXMLContent method is: 00281 % 00282 % char *CanonicalXMLContent(const char *content, 00283 % const WizardBooleanType pedantic) 00284 % 00285 % A description of each parameter follows: 00286 % 00287 % o content: the content. 00288 % 00289 % o pedantic: if true, replace newlines and tabs with their respective 00290 % entities. 00291 % 00292 */ 00293 00294 static unsigned char *ConvertLatin1ToUTF8(const unsigned char *content) 00295 { 00296 register const unsigned char 00297 *p; 00298 00299 register unsigned char 00300 *q; 00301 00302 size_t 00303 length; 00304 00305 unsigned char 00306 *utf8; 00307 00308 unsigned int 00309 c; 00310 00311 length=0; 00312 for (p=content; *p != '\0'; p++) 00313 length+=(*p & 0x80) != 0 ? 2 : 1; 00314 utf8=(unsigned char *) NULL; 00315 if (~length >= 1) 00316 utf8=(unsigned char *) AcquireQuantumMemory(length+1UL,sizeof(*utf8)); 00317 if (utf8 == (unsigned char *) NULL) 00318 return((unsigned char *) NULL); 00319 q=utf8; 00320 for (p=content; *p != '\0'; p++) 00321 { 00322 c=(*p); 00323 if ((c & 0x80) == 0) 00324 *q++=c; 00325 else 00326 { 00327 *q++=0xc0 | ((c >> 6) & 0x3f); 00328 *q++=0x80 | (c & 0x3f); 00329 } 00330 } 00331 *q='\0'; 00332 return(utf8); 00333 } 00334 00335 WizardExport char *CanonicalXMLContent(const char *content, 00336 const WizardBooleanType pedantic) 00337 { 00338 char 00339 *base64, 00340 *canonical_content; 00341 00342 register const unsigned char 00343 *p; 00344 00345 register ssize_t 00346 i; 00347 00348 size_t 00349 extent, 00350 length; 00351 00352 unsigned char 00353 *utf8; 00354 00355 utf8=ConvertLatin1ToUTF8((const unsigned char *) content); 00356 if (utf8 == (unsigned char *) NULL) 00357 return((char *) NULL); 00358 for (p=utf8; *p != '\0'; p++) 00359 if ((*p < 0x20) && (*p != 0x09) && (*p != 0x0a) && (*p != 0x0d)) 00360 break; 00361 if (*p != '\0') 00362 { 00363 /* 00364 String is binary, base64-encode it. 00365 */ 00366 base64=Base64Encode(utf8,strlen((char *) utf8),&length); 00367 utf8=(unsigned char *) RelinquishWizardMemory(utf8); 00368 if (base64 == (char *) NULL) 00369 return((char *) NULL); 00370 canonical_content=AcquireString("<base64>"); 00371 (void) ConcatenateString(&canonical_content,base64); 00372 base64=DestroyString(base64); 00373 (void) ConcatenateString(&canonical_content,"</base64>"); 00374 return(canonical_content); 00375 } 00376 /* 00377 Substitute predefined entities. 00378 */ 00379 i=0; 00380 canonical_content=AcquireString((char *) NULL); 00381 extent=MaxTextExtent; 00382 for (p=utf8; *p != '\0'; p++) 00383 { 00384 if ((i+MaxTextExtent) > (ssize_t) extent) 00385 { 00386 extent+=MaxTextExtent; 00387 canonical_content=(char *) ResizeQuantumMemory(canonical_content,extent, 00388 sizeof(*canonical_content)); 00389 if (canonical_content == (char *) NULL) 00390 return(canonical_content); 00391 } 00392 switch (*p) 00393 { 00394 case '&': 00395 { 00396 i+=FormatLocaleString(canonical_content+i,extent,"&"); 00397 break; 00398 } 00399 case '<': 00400 { 00401 i+=FormatLocaleString(canonical_content+i,extent,"<"); 00402 break; 00403 } 00404 case '>': 00405 { 00406 i+=FormatLocaleString(canonical_content+i,extent,">"); 00407 break; 00408 } 00409 case '"': 00410 { 00411 i+=FormatLocaleString(canonical_content+i,extent,"""); 00412 break; 00413 } 00414 case '\n': 00415 { 00416 if (pedantic == WizardFalse) 00417 { 00418 canonical_content[i++]=(char) (*p); 00419 break; 00420 } 00421 i+=FormatLocaleString(canonical_content+i,extent,"
"); 00422 break; 00423 } 00424 case '\t': 00425 { 00426 if (pedantic == WizardFalse) 00427 { 00428 canonical_content[i++]=(char) (*p); 00429 break; 00430 } 00431 i+=FormatLocaleString(canonical_content+i,extent,"	"); 00432 break; 00433 } 00434 case '\r': 00435 { 00436 i+=FormatLocaleString(canonical_content+i,extent,"
"); 00437 break; 00438 } 00439 default: 00440 { 00441 canonical_content[i++]=(char) (*p); 00442 break; 00443 } 00444 } 00445 } 00446 canonical_content[i]='\0'; 00447 utf8=(unsigned char *) RelinquishWizardMemory(utf8); 00448 return(canonical_content); 00449 } 00450 00451 /* 00452 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00453 % % 00454 % % 00455 % % 00456 % D e s t r o y X M L T r e e % 00457 % % 00458 % % 00459 % % 00460 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00461 % 00462 % DestroyXMLTree() destroys the xml-tree. 00463 % 00464 % The format of the DestroyXMLTree method is: 00465 % 00466 % XMLTreeInfo *DestroyXMLTree(XMLTreeInfo *xml_info) 00467 % 00468 % A description of each parameter follows: 00469 % 00470 % o xml_info: the xml info. 00471 % 00472 */ 00473 00474 static char **DestroyXMLTreeAttributes(char **attributes) 00475 { 00476 register ssize_t 00477 i; 00478 00479 /* 00480 Destroy a tag attribute list. 00481 */ 00482 if ((attributes == (char **) NULL) || (attributes == sentinel)) 00483 return((char **) NULL); 00484 for (i=0; attributes[i] != (char *) NULL; i+=2) 00485 { 00486 /* 00487 Destroy attribute tag and value. 00488 */ 00489 if (attributes[i] != (char *) NULL) 00490 attributes[i]=DestroyString(attributes[i]); 00491 if (attributes[i+1] != (char *) NULL) 00492 attributes[i+1]=DestroyString(attributes[i+1]); 00493 } 00494 attributes=(char **) RelinquishWizardMemory(attributes); 00495 return((char **) NULL); 00496 } 00497 00498 WizardExport XMLTreeInfo *DestroyXMLTree(XMLTreeInfo *xml_info) 00499 { 00500 char 00501 **attributes; 00502 00503 ssize_t 00504 j; 00505 00506 register ssize_t 00507 i; 00508 00509 XMLTreeRoot 00510 *root; 00511 00512 WizardAssert(ResourceDomain,xml_info != (XMLTreeInfo *) NULL); 00513 WizardAssert(ResourceDomain,(xml_info->signature == WizardSignature) || 00514 (((XMLTreeRoot *) xml_info)->signature == WizardSignature)); 00515 (void) LogWizardEvent(TraceEvent,GetWizardModule(),"..."); 00516 if (xml_info->child != (XMLTreeInfo *) NULL) 00517 xml_info->child=DestroyXMLTree(xml_info->child); 00518 if (xml_info->ordered != (XMLTreeInfo *) NULL) 00519 xml_info->ordered=DestroyXMLTree(xml_info->ordered); 00520 if (xml_info->parent == (XMLTreeInfo *) NULL) 00521 { 00522 /* 00523 Free root tag allocations. 00524 */ 00525 root=(XMLTreeRoot *) xml_info; 00526 for (i=NumberPredefinedEntities; root->entities[i]; i+=2) 00527 root->entities[i+1]=DestroyString(root->entities[i+1]); 00528 root->entities=(char **) RelinquishWizardMemory(root->entities); 00529 for (i=0; root->attributes[i] != (char **) NULL; i++) 00530 { 00531 attributes=root->attributes[i]; 00532 if (attributes[0] != (char *) NULL) 00533 attributes[0]=DestroyString(attributes[0]); 00534 for (j=1; attributes[j] != (char *) NULL; j+=3) 00535 { 00536 if (attributes[j] != (char *) NULL) 00537 attributes[j]=DestroyString(attributes[j]); 00538 if (attributes[j+1] != (char *) NULL) 00539 attributes[j+1]=DestroyString(attributes[j+1]); 00540 if (attributes[j+2] != (char *) NULL) 00541 attributes[j+2]=DestroyString(attributes[j+2]); 00542 } 00543 attributes=(char **) RelinquishWizardMemory(attributes); 00544 } 00545 if (root->attributes[0] != (char **) NULL) 00546 root->attributes=(char ***) RelinquishWizardMemory(root->attributes); 00547 if (root->processing_instructions[0] != (char **) NULL) 00548 { 00549 for (i=0; root->processing_instructions[i] != (char **) NULL; i++) 00550 { 00551 for (j=0; root->processing_instructions[i][j] != (char *) NULL; j++) 00552 root->processing_instructions[i][j]=DestroyString( 00553 root->processing_instructions[i][j]); 00554 root->processing_instructions[i][j+1]=DestroyString( 00555 root->processing_instructions[i][j+1]); 00556 root->processing_instructions[i]=(char **) RelinquishWizardMemory( 00557 root->processing_instructions[i]); 00558 } 00559 root->processing_instructions=(char ***) RelinquishWizardMemory( 00560 root->processing_instructions); 00561 } 00562 } 00563 xml_info->attributes=DestroyXMLTreeAttributes(xml_info->attributes); 00564 xml_info->content=DestroyString(xml_info->content); 00565 xml_info->tag=DestroyString(xml_info->tag); 00566 xml_info=(XMLTreeInfo *) RelinquishWizardMemory(xml_info); 00567 return((XMLTreeInfo *) NULL); 00568 } 00569 00570 /* 00571 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00572 % % 00573 % % 00574 % % 00575 % G e t N e x t X M L T r e e T a g % 00576 % % 00577 % % 00578 % % 00579 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00580 % 00581 % GetNextXMLTreeTag() returns the next tag or NULL if not found. 00582 % 00583 % The format of the GetNextXMLTreeTag method is: 00584 % 00585 % XMLTreeInfo *GetNextXMLTreeTag(XMLTreeInfo *xml_info) 00586 % 00587 % A description of each parameter follows: 00588 % 00589 % o xml_info: the xml info. 00590 % 00591 */ 00592 WizardExport XMLTreeInfo *GetNextXMLTreeTag(XMLTreeInfo *xml_info) 00593 { 00594 WizardAssert(ResourceDomain,xml_info != (XMLTreeInfo *) NULL); 00595 WizardAssert(ResourceDomain,(xml_info->signature == WizardSignature) || 00596 (((XMLTreeRoot *) xml_info)->signature == WizardSignature)); 00597 (void) LogWizardEvent(TraceEvent,GetWizardModule(),"..."); 00598 return(xml_info->next); 00599 } 00600 00601 /* 00602 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00603 % % 00604 % % 00605 % % 00606 % G e t X M L T r e e A t t r i b u t e % 00607 % % 00608 % % 00609 % % 00610 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00611 % 00612 % GetXMLTreeAttribute() returns the value of the attribute tag with the 00613 % specified tag if found, otherwise NULL. 00614 % 00615 % The format of the GetXMLTreeAttribute method is: 00616 % 00617 % const char *GetXMLTreeAttribute(XMLTreeInfo *xml_info,const char *tag) 00618 % 00619 % A description of each parameter follows: 00620 % 00621 % o xml_info: the xml info. 00622 % 00623 % o tag: the attribute tag. 00624 % 00625 */ 00626 WizardExport const char *GetXMLTreeAttribute(XMLTreeInfo *xml_info, 00627 const char *tag) 00628 { 00629 ssize_t 00630 j; 00631 00632 register ssize_t 00633 i; 00634 00635 XMLTreeRoot 00636 *root; 00637 00638 WizardAssert(ResourceDomain,xml_info != (XMLTreeInfo *) NULL); 00639 WizardAssert(ResourceDomain,(xml_info->signature == WizardSignature) || 00640 (((XMLTreeRoot *) xml_info)->signature == WizardSignature)); 00641 (void) LogWizardEvent(TraceEvent,GetWizardModule(),"..."); 00642 if (xml_info->attributes == (char **) NULL) 00643 return((const char *) NULL); 00644 i=0; 00645 while ((xml_info->attributes[i] != (char *) NULL) && 00646 (strcmp(xml_info->attributes[i],tag) != 0)) 00647 i+=2; 00648 if (xml_info->attributes[i] != (char *) NULL) 00649 return(xml_info->attributes[i+1]); 00650 root=(XMLTreeRoot*) xml_info; 00651 while (root->root.parent != (XMLTreeInfo *) NULL) 00652 root=(XMLTreeRoot *) root->root.parent; 00653 i=0; 00654 while ((root->attributes[i] != (char **) NULL) && 00655 (strcmp(root->attributes[i][0],xml_info->tag) != 0)) 00656 i++; 00657 if (root->attributes[i] == (char **) NULL) 00658 return((const char *) NULL); 00659 j=1; 00660 while ((root->attributes[i][j] != (char *) NULL) && 00661 (strcmp(root->attributes[i][j],tag) != 0)) 00662 j+=3; 00663 if (root->attributes[i][j] == (char *) NULL) 00664 return((const char *) NULL); 00665 return(root->attributes[i][j+1]); 00666 } 00667 00668 /* 00669 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00670 % % 00671 % % 00672 % % 00673 % G e t X M L T r e e A t t r i b u t e s % 00674 % % 00675 % % 00676 % % 00677 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00678 % 00679 % GetXMLTreeAttributes() injects all attributes associated with the current 00680 % tag in the specified splay-tree. 00681 % 00682 % The format of the GetXMLTreeAttributes method is: 00683 % 00684 % WizardBooleanType GetXMLTreeAttributes(const XMLTreeInfo *xml_info, 00685 % SplayTreeInfo *attributes) 00686 % 00687 % A description of each parameter follows: 00688 % 00689 % o xml_info: the xml info. 00690 % 00691 % o attributes: the attribute splay-tree. 00692 % 00693 */ 00694 WizardExport WizardBooleanType GetXMLTreeAttributes(const XMLTreeInfo *xml_info, 00695 SplayTreeInfo *attributes) 00696 { 00697 register ssize_t 00698 i; 00699 00700 WizardAssert(ResourceDomain,xml_info != (XMLTreeInfo *) NULL); 00701 WizardAssert(ResourceDomain,(xml_info->signature == WizardSignature) || 00702 (((XMLTreeRoot *) xml_info)->signature == WizardSignature)); 00703 (void) LogWizardEvent(TraceEvent,GetWizardModule(),"..."); 00704 WizardAssert(ResourceDomain,attributes != (SplayTreeInfo *) NULL); 00705 if (xml_info->attributes == (char **) NULL) 00706 return(WizardTrue); 00707 i=0; 00708 while (xml_info->attributes[i] != (char *) NULL) 00709 { 00710 (void) AddValueToSplayTree(attributes, 00711 ConstantString(xml_info->attributes[i]), 00712 ConstantString(xml_info->attributes[i+1])); 00713 i+=2; 00714 } 00715 return(WizardTrue); 00716 } 00717 00718 /* 00719 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00720 % % 00721 % % 00722 % % 00723 % G e t X M L T r e e C h i l d % 00724 % % 00725 % % 00726 % % 00727 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00728 % 00729 % GetXMLTreeChild() returns the first child tag with the specified tag if 00730 % found, otherwise NULL. 00731 % 00732 % The format of the GetXMLTreeChild method is: 00733 % 00734 % XMLTreeInfo *GetXMLTreeChild(XMLTreeInfo *xml_info,const char *tag) 00735 % 00736 % A description of each parameter follows: 00737 % 00738 % o xml_info: the xml info. 00739 % 00740 */ 00741 WizardExport XMLTreeInfo *GetXMLTreeChild(XMLTreeInfo *xml_info,const char *tag) 00742 { 00743 XMLTreeInfo 00744 *child; 00745 00746 WizardAssert(ResourceDomain,xml_info != (XMLTreeInfo *) NULL); 00747 WizardAssert(ResourceDomain,(xml_info->signature == WizardSignature) || 00748 (((XMLTreeRoot *) xml_info)->signature == WizardSignature)); 00749 (void) LogWizardEvent(TraceEvent,GetWizardModule(),"..."); 00750 child=xml_info->child; 00751 if (tag != (const char *) NULL) 00752 while ((child != (XMLTreeInfo *) NULL) && (strcmp(child->tag,tag) != 0)) 00753 child=child->sibling; 00754 return(child); 00755 } 00756 00757 /* 00758 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00759 % % 00760 % % 00761 % % 00762 % G e t X M L T r e e C o n t e n t % 00763 % % 00764 % % 00765 % % 00766 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00767 % 00768 % GetXMLTreeContent() returns any content associated with specified 00769 % xml-tree node. 00770 % 00771 % The format of the GetXMLTreeContent method is: 00772 % 00773 % const char *GetXMLTreeContent(XMLTreeInfo *xml_info) 00774 % 00775 % A description of each parameter follows: 00776 % 00777 % o xml_info: the xml info. 00778 % 00779 */ 00780 WizardExport const char *GetXMLTreeContent(XMLTreeInfo *xml_info) 00781 { 00782 WizardAssert(ResourceDomain,xml_info != (XMLTreeInfo *) NULL); 00783 WizardAssert(ResourceDomain,(xml_info->signature == WizardSignature) || 00784 (((XMLTreeRoot *) xml_info)->signature == WizardSignature)); 00785 (void) LogWizardEvent(TraceEvent,GetWizardModule(),"..."); 00786 return(xml_info->content); 00787 } 00788 00789 /* 00790 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00791 % % 00792 % % 00793 % % 00794 % G e t X M L T r e e O r d e r e d % 00795 % % 00796 % % 00797 % % 00798 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00799 % 00800 % GetXMLTreeOrdered() returns the next ordered node if found, otherwise NULL. 00801 % 00802 % The format of the GetXMLTreeOrdered method is: 00803 % 00804 % XMLTreeInfo *GetXMLTreeOrdered(XMLTreeInfo *xml_info) 00805 % 00806 % A description of each parameter follows: 00807 % 00808 % o xml_info: the xml info. 00809 % 00810 */ 00811 WizardExport XMLTreeInfo *GetXMLTreeOrdered(XMLTreeInfo *xml_info) 00812 { 00813 WizardAssert(ResourceDomain,xml_info != (XMLTreeInfo *) NULL); 00814 WizardAssert(ResourceDomain,(xml_info->signature == WizardSignature) || 00815 (((XMLTreeRoot *) xml_info)->signature == WizardSignature)); 00816 (void) LogWizardEvent(TraceEvent,GetWizardModule(),"..."); 00817 return(xml_info->ordered); 00818 } 00819 00820 /* 00821 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00822 % % 00823 % % 00824 % % 00825 % G e t X M L T r e e P a t h % 00826 % % 00827 % % 00828 % % 00829 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00830 % 00831 % GetXMLTreePath() traverses the XML-tree as defined by the specified path 00832 % and returns the node if found, otherwise NULL. 00833 % 00834 % The format of the GetXMLTreePath method is: 00835 % 00836 % XMLTreeInfo *GetXMLTreePath(XMLTreeInfo *xml_info,const char *path) 00837 % 00838 % A description of each parameter follows: 00839 % 00840 % o xml_info: the xml info. 00841 % 00842 % o path: the path (e.g. property/elapsed-time). 00843 % 00844 */ 00845 WizardExport XMLTreeInfo *GetXMLTreePath(XMLTreeInfo *xml_info,const char *path) 00846 { 00847 char 00848 **components, 00849 subnode[MaxTextExtent], 00850 tag[MaxTextExtent]; 00851 00852 ssize_t 00853 j; 00854 00855 register ssize_t 00856 i; 00857 00858 XMLTreeInfo 00859 *node; 00860 00861 size_t 00862 number_components; 00863 00864 WizardAssert(ResourceDomain,xml_info != (XMLTreeInfo *) NULL); 00865 WizardAssert(ResourceDomain,(xml_info->signature == WizardSignature) || 00866 (((XMLTreeRoot *) xml_info)->signature == WizardSignature)); 00867 (void) LogWizardEvent(TraceEvent,GetWizardModule(),"..."); 00868 node=xml_info; 00869 components=GetPathComponents(path,&number_components); 00870 if (components == (char **) NULL) 00871 return((XMLTreeInfo *) NULL); 00872 for (i=0; i < (ssize_t) number_components; i++) 00873 { 00874 GetPathComponent(components[i],SubnodePath,subnode); 00875 GetPathComponent(components[i],CanonicalPath,tag); 00876 node=GetXMLTreeChild(node,tag); 00877 if (node == (XMLTreeInfo *) NULL) 00878 break; 00879 for (j=StringToLong(subnode)-1; j > 0; j--) 00880 { 00881 node=GetXMLTreeOrdered(node); 00882 if (node == (XMLTreeInfo *) NULL) 00883 break; 00884 } 00885 if (node == (XMLTreeInfo *) NULL) 00886 break; 00887 components[i]=DestroyString(components[i]); 00888 } 00889 for ( ; i < (ssize_t) number_components; i++) 00890 components[i]=DestroyString(components[i]); 00891 components=(char **) RelinquishWizardMemory(components); 00892 return(node); 00893 } 00894 00895 /* 00896 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00897 % % 00898 % % 00899 % % 00900 % G e t X M L T r e e P r o c e s s i n g I n s t r u c t i o n s % 00901 % % 00902 % % 00903 % % 00904 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00905 % 00906 % GetXMLTreeProcessingInstructions() returns a null terminated array of 00907 % processing instructions for the given target. 00908 % 00909 % The format of the GetXMLTreeProcessingInstructions method is: 00910 % 00911 % const char **GetXMLTreeProcessingInstructions(XMLTreeInfo *xml_info, 00912 % const char *target) 00913 % 00914 % A description of each parameter follows: 00915 % 00916 % o xml_info: the xml info. 00917 % 00918 */ 00919 WizardExport const char **GetXMLTreeProcessingInstructions( 00920 XMLTreeInfo *xml_info,const char *target) 00921 { 00922 register ssize_t 00923 i; 00924 00925 XMLTreeRoot 00926 *root; 00927 00928 WizardAssert(ResourceDomain,xml_info != (XMLTreeInfo *) NULL); 00929 WizardAssert(ResourceDomain,(xml_info->signature == WizardSignature) || 00930 (((XMLTreeRoot *) xml_info)->signature == WizardSignature)); 00931 (void) LogWizardEvent(TraceEvent,GetWizardModule(),"..."); 00932 root=(XMLTreeRoot *) xml_info; 00933 while (root->root.parent != (XMLTreeInfo *) NULL) 00934 root=(XMLTreeRoot *) root->root.parent; 00935 i=0; 00936 while ((root->processing_instructions[i] != (char **) NULL) && 00937 (strcmp(root->processing_instructions[i][0],target) != 0)) 00938 i++; 00939 if (root->processing_instructions[i] == (char **) NULL) 00940 return((const char **) sentinel); 00941 return((const char **) (root->processing_instructions[i]+1)); 00942 } 00943 00944 /* 00945 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00946 % % 00947 % % 00948 % % 00949 % G e t X M L T r e e S i b l i n g % 00950 % % 00951 % % 00952 % % 00953 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00954 % 00955 % GetXMLTreeSibling() returns the node sibling if found, otherwise NULL. 00956 % 00957 % The format of the GetXMLTreeSibling method is: 00958 % 00959 % XMLTreeInfo *GetXMLTreeSibling(XMLTreeInfo *xml_info) 00960 % 00961 % A description of each parameter follows: 00962 % 00963 % o xml_info: the xml info. 00964 % 00965 */ 00966 WizardExport XMLTreeInfo *GetXMLTreeSibling(XMLTreeInfo *xml_info) 00967 { 00968 WizardAssert(ResourceDomain,xml_info != (XMLTreeInfo *) NULL); 00969 WizardAssert(ResourceDomain,(xml_info->signature == WizardSignature) || 00970 (((XMLTreeRoot *) xml_info)->signature == WizardSignature)); 00971 (void) LogWizardEvent(TraceEvent,GetWizardModule(),"..."); 00972 return(xml_info->sibling); 00973 } 00974 00975 /* 00976 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00977 % % 00978 % % 00979 % % 00980 % G e t X M L T r e e T a g % 00981 % % 00982 % % 00983 % % 00984 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00985 % 00986 % GetXMLTreeTag() returns the tag associated with specified xml-tree node. 00987 % 00988 % The format of the GetXMLTreeTag method is: 00989 % 00990 % const char *GetXMLTreeTag(XMLTreeInfo *xml_info) 00991 % 00992 % A description of each parameter follows: 00993 % 00994 % o xml_info: the xml info. 00995 % 00996 */ 00997 WizardExport const char *GetXMLTreeTag(XMLTreeInfo *xml_info) 00998 { 00999 WizardAssert(ResourceDomain,xml_info != (XMLTreeInfo *) NULL); 01000 WizardAssert(ResourceDomain,(xml_info->signature == WizardSignature) || 01001 (((XMLTreeRoot *) xml_info)->signature == WizardSignature)); 01002 (void) LogWizardEvent(TraceEvent,GetWizardModule(),"..."); 01003 return(xml_info->tag); 01004 } 01005 01006 /* 01007 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01008 % % 01009 % % 01010 % % 01011 % I n s e r t I n t o T a g X M L T r e e % 01012 % % 01013 % % 01014 % % 01015 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01016 % 01017 % InsertTagIntoXMLTree() inserts a tag at an offset relative to the start of 01018 % the parent tag's character content. This method returns the child tag. 01019 % 01020 % The format of the InsertTagIntoXMLTree method is: 01021 % 01022 % XMLTreeInfo *InsertTagIntoXMLTree(XMLTreeInfo *xml_info, 01023 % XMLTreeInfo *child,const size_t offset) 01024 % 01025 % A description of each parameter follows: 01026 % 01027 % o xml_info: the xml info. 01028 % 01029 % o child: the child tag. 01030 % 01031 % o offset: the tag offset. 01032 % 01033 */ 01034 WizardExport XMLTreeInfo *InsertTagIntoXMLTree(XMLTreeInfo *xml_info, 01035 XMLTreeInfo *child,const size_t offset) 01036 { 01037 XMLTreeInfo 01038 *head, 01039 *node, 01040 *previous; 01041 01042 child->ordered=(XMLTreeInfo *) NULL; 01043 child->sibling=(XMLTreeInfo *) NULL; 01044 child->next=(XMLTreeInfo *) NULL; 01045 child->offset=offset; 01046 child->parent=xml_info; 01047 if (xml_info->child == (XMLTreeInfo *) NULL) 01048 { 01049 xml_info->child=child; 01050 return(child); 01051 } 01052 head=xml_info->child; 01053 if (head->offset > offset) 01054 { 01055 child->ordered=head; 01056 xml_info->child=child; 01057 } 01058 else 01059 { 01060 node=head; 01061 while ((node->ordered != (XMLTreeInfo *) NULL) && 01062 (node->ordered->offset <= offset)) 01063 node=node->ordered; 01064 child->ordered=node->ordered; 01065 node->ordered=child; 01066 } 01067 previous=(XMLTreeInfo *) NULL; 01068 node=head; 01069 while ((node != (XMLTreeInfo *) NULL) && (strcmp(node->tag,child->tag) != 0)) 01070 { 01071 previous=node; 01072 node=node->sibling; 01073 } 01074 if ((node != (XMLTreeInfo *) NULL) && (node->offset <= offset)) 01075 { 01076 while ((node->next != (XMLTreeInfo *) NULL) && 01077 (node->next->offset <= offset)) 01078 node=node->next; 01079 child->next=node->next; 01080 node->next=child; 01081 } 01082 else 01083 { 01084 if ((previous != (XMLTreeInfo *) NULL) && (node != (XMLTreeInfo *) NULL)) 01085 previous->sibling=node->sibling; 01086 child->next=node; 01087 previous=(XMLTreeInfo *) NULL; 01088 node=head; 01089 while ((node != (XMLTreeInfo *) NULL) && (node->offset <= offset)) 01090 { 01091 previous=node; 01092 node=node->sibling; 01093 } 01094 child->sibling=node; 01095 if (previous != (XMLTreeInfo *) NULL) 01096 previous->sibling=child; 01097 } 01098 return(child); 01099 } 01100 01101 /* 01102 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01103 % % 01104 % % 01105 % % 01106 % N e w X M L T r e e % 01107 % % 01108 % % 01109 % % 01110 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01111 % 01112 % NewXMLTree() returns a XMLTreeInfo xml-tree as defined by the specified 01113 % XML string. 01114 % 01115 % The format of the NewXMLTree method is: 01116 % 01117 % XMLTreeInfo *NewXMLTree(const char *xml,ExceptionInfo *exception) 01118 % 01119 % A description of each parameter follows: 01120 % 01121 % o xml: The XML string. 01122 % 01123 % o exception: Return any errors or warnings in this structure. 01124 % 01125 */ 01126 01127 static char *ConvertUTF16ToUTF8(const char *content,size_t *length) 01128 { 01129 char 01130 *utf8; 01131 01132 int 01133 bits, 01134 byte, 01135 c, 01136 encoding; 01137 01138 ssize_t 01139 j; 01140 01141 register ssize_t 01142 i; 01143 01144 size_t 01145 extent; 01146 01147 utf8=(char *) AcquireQuantumMemory(*length,sizeof(*utf8)); 01148 if (utf8 == (char *) NULL) 01149 return((char *) NULL); 01150 encoding=(*content == '\xFE') ? 1 : (*content == '\xFF') ? 0 : -1; 01151 if (encoding == -1) 01152 { 01153 /* 01154 Already UTF-8. 01155 */ 01156 (void) CopyWizardMemory(utf8,content,*length*sizeof(*utf8)); 01157 return(utf8); 01158 } 01159 j=0; 01160 extent=(*length); 01161 for (i=2; i < (ssize_t) (*length-1); i+=2) 01162 { 01163 c=(encoding != 0) ? ((content[i] & 0xff) << 8) | (content[i+1] & 0xff) : 01164 ((content[i+1] & 0xff) << 8) | (content[i] & 0xff); 01165 if ((c >= 0xd800) && (c <= 0xdfff) && ((i+=2) < (ssize_t) (*length-1))) 01166 { 01167 byte=(encoding != 0) ? ((content[i] & 0xff) << 8) | 01168 (content[i+1] & 0xff) : ((content[i+1] & 0xff) << 8) | 01169 (content[i] & 0xff); 01170 c=(((c & 0x3ff) << 10) | (byte & 0x3ff))+0x10000; 01171 } 01172 if ((size_t) (j+MaxTextExtent) > extent) 01173 { 01174 extent=(size_t) j+MaxTextExtent; 01175 utf8=(char *) ResizeQuantumMemory(utf8,extent,sizeof(*utf8)); 01176 if (utf8 == (char *) NULL) 01177 return(utf8); 01178 } 01179 if (c < 0x80) 01180 { 01181 utf8[j]=c; 01182 j++; 01183 continue; 01184 } 01185 /* 01186 Multi-byte UTF-8 sequence. 01187 */ 01188 byte=c; 01189 for (bits=0; byte != 0; byte/=2) 01190 bits++; 01191 bits=(bits-2)/5; 01192 utf8[j++]=(0xFF << (7-bits)) | (c >> (6*bits)); 01193 while (bits != 0) 01194 { 01195 bits--; 01196 utf8[j]=0x80 | ((c >> (6*bits)) & 0x3f); 01197 j++; 01198 } 01199 } 01200 *length=(size_t) j; 01201 return((char *) ResizeQuantumMemory(utf8,*length,sizeof(*utf8))); 01202 } 01203 01204 static char *ParseEntities(char *xml,char **entities,int state) 01205 { 01206 char 01207 *entity; 01208 01209 int 01210 byte, 01211 c; 01212 01213 register char 01214 *p, 01215 *q; 01216 01217 register ssize_t 01218 i; 01219 01220 size_t 01221 extent, 01222 length; 01223 01224 ssize_t 01225 offset; 01226 01227 /* 01228 Normalize line endings. 01229 */ 01230 p=xml; 01231 q=xml; 01232 for ( ; *xml != '\0'; xml++) 01233 while (*xml == '\r') 01234 { 01235 *(xml++)='\n'; 01236 if (*xml == '\n') 01237 (void) CopyWizardMemory(xml,xml+1,strlen(xml)); 01238 } 01239 for (xml=p; ; ) 01240 { 01241 while ((*xml != '\0') && (*xml != '&') && ((*xml != '%') || 01242 (state != '%')) && (isspace((int) ((unsigned char) *xml) == 0))) 01243 xml++; 01244 if (*xml == '\0') 01245 break; 01246 /* 01247 States include: 01248 '&' for general entity decoding 01249 '%' for parameter entity decoding 01250 'c' for CDATA sections 01251 ' ' for attributes normalization 01252 '*' for non-CDATA attributes normalization 01253 */ 01254 if ((state != 'c') && (strncmp(xml,"&#",2) == 0)) 01255 { 01256 /* 01257 Character reference. 01258 */ 01259 if (xml[2] != 'x') 01260 c=strtol(xml+2,&entity,10); /* base 10 */ 01261 else 01262 c=strtol(xml+3,&entity,16); /* base 16 */ 01263 if ((c == 0) || (*entity != ';')) 01264 { 01265 /* 01266 Not a character reference. 01267 */ 01268 xml++; 01269 continue; 01270 } 01271 if (c < 0x80) 01272 *(xml++)=c; 01273 else 01274 { 01275 /* 01276 Multi-byte UTF-8 sequence. 01277 */ 01278 byte=c; 01279 for (i=0; byte != 0; byte/=2) 01280 i++; 01281 i=(i-2)/5; 01282 *xml=(char) ((0xFF << (7-i)) | (c >> (6*i))); 01283 xml++; 01284 while (i != 0) 01285 { 01286 i--; 01287 *xml=(char) (0x80 | ((c >> (6*i)) & 0x3F)); 01288 xml++; 01289 } 01290 } 01291 (void) CopyWizardMemory(xml,strchr(xml,';')+1,strlen(strchr(xml,';'))); 01292 } 01293 else 01294 if (((*xml == '&') && ((state == '&') || (state == ' ') || 01295 (state == '*'))) || ((state == '%') && (*xml == '%'))) 01296 { 01297 /* 01298 Find entity in the list. 01299 */ 01300 i=0; 01301 while ((entities[i] != (char *) NULL) && 01302 (strncmp(xml+1,entities[i],strlen(entities[i])) != 0)) 01303 i+=2; 01304 if (entities[i++] == (char *) NULL) 01305 xml++; 01306 else 01307 { 01308 /* 01309 Found a match. 01310 */ 01311 length=strlen(entities[i]); 01312 entity=strchr(xml,';'); 01313 if ((length-1L) >= (size_t) (entity-xml)) 01314 { 01315 offset=(ssize_t) (xml-p); 01316 extent=(size_t) (offset+length+strlen(entity)); 01317 if (p != q) 01318 p=(char *) ResizeQuantumMemory(p,extent,sizeof(*p)); 01319 else 01320 { 01321 char 01322 *xml; 01323 01324 xml=(char *) AcquireQuantumMemory(extent,sizeof(*xml)); 01325 if (xml != (char *) NULL) 01326 { 01327 (void) CopyWizardString(xml,p,extent*sizeof(*xml)); 01328 p=xml; 01329 } 01330 } 01331 if (p == (char *) NULL) 01332 ThrowFatalException(ResourceFatalError, 01333 "unable to acquire string `%s'"); 01334 xml=p+offset; 01335 entity=strchr(xml,';'); 01336 } 01337 (void) CopyWizardMemory(xml+length,entity+1,strlen(entity)); 01338 (void) strncpy(xml,entities[i],length); 01339 } 01340 } 01341 else 01342 if (((state == ' ') || (state == '*')) && 01343 (isspace((int) ((unsigned char) *xml) != 0))) 01344 *(xml++)=' '; 01345 else 01346 xml++; 01347 } 01348 if (state == '*') 01349 { 01350 /* 01351 Normalize spaces for non-CDATA attributes. 01352 */ 01353 for (xml=p; *xml != '\0'; xml++) 01354 { 01355 i=(ssize_t) strspn(xml," "); 01356 if (i != 0) 01357 (void) CopyWizardMemory(xml,xml+i,strlen(xml+i)+1); 01358 while ((*xml != '\0') && (*xml != ' ')) 01359 xml++; 01360 } 01361 xml--; 01362 if ((xml >= p) && (*xml == ' ')) 01363 *xml='\0'; 01364 } 01365 return(p == q ? ConstantString(p) : p); 01366 } 01367 01368 void ParseCharacterContent(XMLTreeRoot *root,char *xml,const size_t length, 01369 const char state) 01370 { 01371 XMLTreeInfo 01372 *xml_info; 01373 01374 xml_info=root->node; 01375 if ((xml_info == (XMLTreeInfo *) NULL) || (xml_info->tag == (char *) NULL) || 01376 (length == 0)) 01377 return; 01378 xml[length]='\0'; 01379 xml=ParseEntities(xml,root->entities,state); 01380 if (*xml_info->content != '\0') 01381 { 01382 (void) ConcatenateString(&xml_info->content,xml); 01383 xml=DestroyString(xml); 01384 } 01385 else 01386 { 01387 if (xml_info->content != (char *) NULL) 01388 xml_info->content=DestroyString(xml_info->content); 01389 xml_info->content=xml; 01390 } 01391 } 01392 01393 static XMLTreeInfo *ParseCloseTag(XMLTreeRoot *root,char *tag, 01394 char *wizard_unused(xml),ExceptionInfo *exception) 01395 { 01396 if ((root->node == (XMLTreeInfo *) NULL) || 01397 (root->node->tag == (char *) NULL) || (strcmp(tag,root->node->tag) != 0)) 01398 { 01399 (void) ThrowWizardException(exception,GetWizardModule(),OptionWarning, 01400 "unexpected closing tag </%s>",tag); 01401 return(&root->root); 01402 } 01403 root->node=root->node->parent; 01404 return((XMLTreeInfo *) NULL); 01405 } 01406 01407 static WizardBooleanType ValidateEntities(char *tag,char *xml,char **entities) 01408 { 01409 register ssize_t 01410 i; 01411 01412 /* 01413 Check for circular entity references. 01414 */ 01415 for ( ; ; xml++) 01416 { 01417 while ((*xml != '\0') && (*xml != '&')) 01418 xml++; 01419 if (*xml == '\0') 01420 return(WizardTrue); 01421 if (strncmp(xml+1,tag,strlen(tag)) == 0) 01422 return(WizardFalse); 01423 i=0; 01424 while ((entities[i] != (char *) NULL) && 01425 (strncmp(entities[i],xml+1,strlen(entities[i]) == 0))) 01426 i+=2; 01427 if ((entities[i] != (char *) NULL) && 01428 (ValidateEntities(tag,entities[i+1],entities) == 0)) 01429 return(WizardFalse); 01430 } 01431 return(WizardTrue); 01432 } 01433 01434 static void ParseProcessingInstructions(XMLTreeRoot *root,char *xml, 01435 size_t length) 01436 { 01437 char 01438 *target; 01439 01440 ssize_t 01441 j; 01442 01443 register ssize_t 01444 i; 01445 01446 target=xml; 01447 xml[length]='\0'; 01448 xml+=strcspn(xml,XMLWhitespace); 01449 if (*xml != '\0') 01450 { 01451 *xml='\0'; 01452 xml+=strspn(xml+1,XMLWhitespace)+1; 01453 } 01454 if (strcmp(target,"xml") == 0) 01455 { 01456 xml=strstr(xml,"standalone"); 01457 if ((xml != (char *) NULL) && 01458 (strncmp(xml+strspn(xml+10,XMLWhitespace "='\"")+10,"yes",3) == 0)) 01459 root->standalone=WizardTrue; 01460 return; 01461 } 01462 if (root->processing_instructions[0] == (char **) NULL) 01463 { 01464 root->processing_instructions=(char ***) AcquireWizardMemory(sizeof( 01465 *root->processing_instructions)); 01466 if (root->processing_instructions ==(char ***) NULL) 01467 ThrowFatalException(ResourceFatalError,"unable to acquire string `%s'"); 01468 *root->processing_instructions=(char **) NULL; 01469 } 01470 i=0; 01471 while ((root->processing_instructions[i] != (char **) NULL) && 01472 (strcmp(target,root->processing_instructions[i][0]) != 0)) 01473 i++; 01474 if (root->processing_instructions[i] == (char **) NULL) 01475 { 01476 root->processing_instructions=(char ***) ResizeQuantumMemory( 01477 root->processing_instructions,(size_t) (i+2), 01478 sizeof(*root->processing_instructions)); 01479 if (root->processing_instructions == (char ***) NULL) 01480 ThrowFatalException(ResourceFatalError,"unable to acquire string `%s'"); 01481 root->processing_instructions[i]=(char **) AcquireQuantumMemory(3, 01482 sizeof(**root->processing_instructions)); 01483 if (root->processing_instructions[i] == (char **) NULL) 01484 ThrowFatalException(ResourceFatalError,"unable to acquire string `%s'"); 01485 root->processing_instructions[i+1]=(char **) NULL; 01486 root->processing_instructions[i][0]=ConstantString(target); 01487 root->processing_instructions[i][1]=(char *) 01488 root->processing_instructions[i+1]; 01489 root->processing_instructions[i+1]=(char **) NULL; 01490 root->processing_instructions[i][2]=ConstantString(""); 01491 } 01492 j=1; 01493 while (root->processing_instructions[i][j] != (char *) NULL) 01494 j++; 01495 root->processing_instructions[i]=(char **) ResizeQuantumMemory( 01496 root->processing_instructions[i],(size_t) (j+3), 01497 sizeof(**root->processing_instructions)); 01498 if (root->processing_instructions[i] == (char **) NULL) 01499 ThrowFatalException(ResourceFatalError,"unable to acquire string `%s'"); 01500 root->processing_instructions[i][j+2]=(char *) ResizeQuantumMemory( 01501 root->processing_instructions[i][j+1],(size_t) (j+1), 01502 sizeof(**root->processing_instructions)); 01503 if (root->processing_instructions[i][j+2] == (char *) NULL) 01504 ThrowFatalException(ResourceFatalError,"unable to acquire string `%s'"); 01505 (void) CopyWizardString(root->processing_instructions[i][j+2]+j-1, 01506 root->root.tag != (char *) NULL ? ">" : "<",2); 01507 root->processing_instructions[i][j+1]=(char *) NULL; 01508 root->processing_instructions[i][j]=ConstantString(xml); 01509 } 01510 01511 static WizardBooleanType ParseInternalDoctype(XMLTreeRoot *root,char *xml, 01512 size_t length,ExceptionInfo *exception) 01513 { 01514 char 01515 *c, 01516 **entities, 01517 *n, 01518 **predefined_entitites, 01519 q, 01520 *t, 01521 *v; 01522 01523 ssize_t 01524 j; 01525 01526 register ssize_t 01527 i; 01528 01529 n=(char *) NULL; 01530 predefined_entitites=(char **) AcquireWizardMemory(sizeof(sentinel)); 01531 if (predefined_entitites == (char **) NULL) 01532 { 01533 (void) ThrowWizardException(exception,GetWizardModule(),ResourceError, 01534 "memory allocation failed `%s'",strerror(errno)); 01535 return(WizardFalse); 01536 } 01537 (void) CopyWizardMemory(predefined_entitites,sentinel,sizeof(sentinel)); 01538 for (xml[length]='\0'; xml != (char *) NULL; ) 01539 { 01540 while ((*xml != '\0') && (*xml != '<') && (*xml != '%')) 01541 xml++; 01542 if (*xml == '\0') 01543 break; 01544 if (strncmp(xml,"<!ENTITY",8) == 0) 01545 { 01546 /* 01547 Parse entity definitions. 01548 */ 01549 xml+=strspn(xml+8,XMLWhitespace)+8; 01550 c=xml; 01551 n=xml+strspn(xml,XMLWhitespace "%"); 01552 xml=n+strcspn(n,XMLWhitespace); 01553 *xml=';'; 01554 v=xml+strspn(xml+1,XMLWhitespace)+1; 01555 q=(*v); 01556 v++; 01557 if ((q != '"') && (q != '\'')) 01558 { 01559 /* 01560 Skip externals. 01561 */ 01562 xml=strchr(xml,'>'); 01563 continue; 01564 } 01565 entities=(*c == '%') ? predefined_entitites : root->entities; 01566 for (i=0; entities[i] != (char *) NULL; i++) ; 01567 entities=(char **) ResizeQuantumMemory(entities,(size_t) (i+3), 01568 sizeof(*entities)); 01569 if (entities == (char **) NULL) 01570 ThrowFatalException(ResourceFatalError, 01571 "unable to acquire string `%s'"); 01572 if (*c == '%') 01573 predefined_entitites=entities; 01574 else 01575 root->entities=entities; 01576 xml++; 01577 *xml='\0'; 01578 xml=strchr(v,q); 01579 if (xml != (char *) NULL) 01580 { 01581 *xml='\0'; 01582 xml++; 01583 } 01584 entities[i+1]=ParseEntities(v,predefined_entitites,'%'); 01585 entities[i+2]=(char *) NULL; 01586 if (ValidateEntities(n,entities[i+1],entities) != WizardFalse) 01587 entities[i]=n; 01588 else 01589 { 01590 if (entities[i+1] != v) 01591 entities[i+1]=DestroyString(entities[i+1]); 01592 (void) ThrowWizardException(exception,GetWizardModule(), 01593 OptionWarning,"circular entity declaration &%s",n); 01594 predefined_entitites=(char **) RelinquishWizardMemory( 01595 predefined_entitites); 01596 return(WizardFalse); 01597 } 01598 } 01599 else 01600 if (strncmp(xml,"<!ATTLIST",9) == 0) 01601 { 01602 /* 01603 Parse default attributes. 01604 */ 01605 t=xml+strspn(xml+9,XMLWhitespace)+9; 01606 if (*t == '\0') 01607 { 01608 (void) ThrowWizardException(exception,GetWizardModule(), 01609 OptionWarning,"unclosed <!ATTLIST"); 01610 predefined_entitites=(char **) RelinquishWizardMemory( 01611 predefined_entitites); 01612 return(WizardFalse); 01613 } 01614 xml=t+strcspn(t,XMLWhitespace ">"); 01615 if (*xml == '>') 01616 continue; 01617 *xml='\0'; 01618 i=0; 01619 while ((root->attributes[i] != (char **) NULL) && 01620 (strcmp(n,root->attributes[i][0]) != 0)) 01621 i++; 01622 while ((*(n=xml+strspn(xml+1,XMLWhitespace)+1) != '\0') && 01623 (*n != '>')) 01624 { 01625 xml=n+strcspn(n,XMLWhitespace); 01626 if (*xml != '\0') 01627 *xml='\0'; 01628 else 01629 { 01630 (void) ThrowWizardException(exception,GetWizardModule(), 01631 OptionWarning,"malformed <!ATTLIST"); 01632 predefined_entitites=(char **) RelinquishWizardMemory( 01633 predefined_entitites); 01634 return(WizardFalse); 01635 } 01636 xml+=strspn(xml+1,XMLWhitespace)+1; 01637 c=(char *) (strncmp(xml,"CDATA",5) != 0 ? "*" : " "); 01638 if (strncmp(xml,"NOTATION",8) == 0) 01639 xml+=strspn(xml+8,XMLWhitespace)+8; 01640 xml=(*xml == '(') ? strchr(xml,')') : xml+ 01641 strcspn(xml,XMLWhitespace); 01642 if (xml == (char *) NULL) 01643 { 01644 (void) ThrowWizardException(exception,GetWizardModule(), 01645 OptionWarning,"malformed <!ATTLIST"); 01646 predefined_entitites=(char **) RelinquishWizardMemory( 01647 predefined_entitites); 01648 return(WizardFalse); 01649 } 01650 xml+=strspn(xml,XMLWhitespace ")"); 01651 if (strncmp(xml,"#FIXED",6) == 0) 01652 xml+=strspn(xml+6,XMLWhitespace)+6; 01653 if (*xml == '#') 01654 { 01655 xml+=strcspn(xml,XMLWhitespace ">")-1; 01656 if (*c == ' ') 01657 continue; 01658 v=(char *) NULL; 01659 } 01660 else 01661 if (((*xml == '"') || (*xml == '\'')) && 01662 ((xml=strchr(v=xml+1,*xml)) != (char *) NULL)) 01663 *xml='\0'; 01664 else 01665 { 01666 (void) ThrowWizardException(exception,GetWizardModule(), 01667 OptionWarning,"malformed <!ATTLIST"); 01668 predefined_entitites=(char **) RelinquishWizardMemory( 01669 predefined_entitites); 01670 return(WizardFalse); 01671 } 01672 if (root->attributes[i] == (char **) NULL) 01673 { 01674 /* 01675 New attribute tag. 01676 */ 01677 if (i == 0) 01678 root->attributes=(char ***) AcquireQuantumMemory(2, 01679 sizeof(*root->attributes)); 01680 else 01681 root->attributes=(char ***) ResizeQuantumMemory( 01682 root->attributes,(size_t) (i+2), 01683 sizeof(*root->attributes)); 01684 if (root->attributes == (char ***) NULL) 01685 ThrowFatalException(ResourceFatalError, 01686 "unable to acquire string `%s'"); 01687 root->attributes[i]=(char **) AcquireQuantumMemory(2, 01688 sizeof(*root->attributes)); 01689 if (root->attributes[i] == (char **) NULL) 01690 ThrowFatalException(ResourceFatalError, 01691 "unable to acquire string `%s'"); 01692 root->attributes[i][0]=ConstantString(t); 01693 root->attributes[i][1]=(char *) NULL; 01694 root->attributes[i+1]=(char **) NULL; 01695 } 01696 for (j=1; root->attributes[i][j] != (char *) NULL; j+=3) ; 01697 root->attributes[i]=(char **) ResizeQuantumMemory( 01698 root->attributes[i],(size_t) (j+4),sizeof(*root->attributes)); 01699 if (root->attributes[i] == (char **) NULL) 01700 ThrowFatalException(ResourceFatalError, 01701 "unable to acquire string `%s'"); 01702 root->attributes[i][j+3]=(char *) NULL; 01703 root->attributes[i][j+2]=ConstantString(c); 01704 root->attributes[i][j+1]=(char *) NULL; 01705 if (v != (char *) NULL) 01706 root->attributes[i][j+1]=ParseEntities(v,root->entities,*c); 01707 root->attributes[i][j]=ConstantString(n); 01708 } 01709 } 01710 else 01711 if (strncmp(xml, "<!--", 4) == 0) 01712 xml=strstr(xml+4,"-->"); 01713 else 01714 if (strncmp(xml,"<?", 2) == 0) 01715 { 01716 c=xml+2; 01717 xml=strstr(c,"?>"); 01718 if (xml != (char *) NULL) 01719 { 01720 ParseProcessingInstructions(root,c,(size_t) (xml-c)); 01721 xml++; 01722 } 01723 } 01724 else 01725 if (*xml == '<') 01726 xml=strchr(xml,'>'); 01727 else 01728 if ((*(xml++) == '%') && (root->standalone == WizardFalse)) 01729 break; 01730 } 01731 predefined_entitites=(char **) RelinquishWizardMemory(predefined_entitites); 01732 return(WizardTrue); 01733 } 01734 01735 static void ParseOpenTag(XMLTreeRoot *root,char *tag,char **attributes) 01736 { 01737 XMLTreeInfo 01738 *xml_info; 01739 01740 xml_info=root->node; 01741 if (xml_info->tag == (char *) NULL) 01742 xml_info->tag=ConstantString(tag); 01743 else 01744 xml_info=AddChildToXMLTree(xml_info,tag,strlen(xml_info->content)); 01745 xml_info->attributes=attributes; 01746 root->node=xml_info; 01747 } 01748 01749 WizardExport XMLTreeInfo *NewXMLTree(const char *xml,ExceptionInfo *exception) 01750 { 01751 char 01752 **attribute, 01753 **attributes, 01754 *tag, 01755 *utf8; 01756 01757 int 01758 c, 01759 terminal; 01760 01761 ssize_t 01762 j, 01763 l; 01764 01765 register char 01766 *p; 01767 01768 register ssize_t 01769 i; 01770 01771 size_t 01772 length; 01773 01774 WizardBooleanType 01775 status; 01776 01777 XMLTreeRoot 01778 *root; 01779 01780 /* 01781 Convert xml-string to UTF8. 01782 */ 01783 if ((xml == (const char *) NULL) || (strlen(xml) == 0)) 01784 { 01785 (void) ThrowWizardException(exception,GetWizardModule(),OptionWarning, 01786 "root tag missing"); 01787 return((XMLTreeInfo *) NULL); 01788 } 01789 root=(XMLTreeRoot *) NewXMLTreeTag((char *) NULL); 01790 length=strlen(xml); 01791 utf8=ConvertUTF16ToUTF8(xml,&length); 01792 if (utf8 == (char *) NULL) 01793 { 01794 (void) ThrowWizardException(exception,GetWizardModule(),ResourceError, 01795 "memory allocation failed `%s'",strerror(errno)); 01796 return((XMLTreeInfo *) NULL); 01797 } 01798 terminal=utf8[length-1]; 01799 utf8[length-1]='\0'; 01800 p=utf8; 01801 while ((*p != '\0') && (*p != '<')) 01802 p++; 01803 if (*p == '\0') 01804 { 01805 (void) ThrowWizardException(exception,GetWizardModule(),OptionWarning, 01806 "root tag missing"); 01807 utf8=DestroyString(utf8); 01808 return((XMLTreeInfo *) NULL); 01809 } 01810 attribute=(char **) NULL; 01811 for (p++; ; p++) 01812 { 01813 attributes=(char **) sentinel; 01814 tag=p; 01815 if ((isalpha((int) ((unsigned char) *p)) !=0) || (*p == '_') || 01816 (*p == ':') || (*p < '\0')) 01817 { 01818 /* 01819 Tag. 01820 */ 01821 if (root->node == (XMLTreeInfo *) NULL) 01822 { 01823 (void) ThrowWizardException(exception,GetWizardModule(), 01824 OptionWarning,"root tag missing"); 01825 utf8=DestroyString(utf8); 01826 return(&root->root); 01827 } 01828 p+=strcspn(p,XMLWhitespace "/>"); 01829 while (isspace((int) ((unsigned char) *p)) != 0) 01830 *p++='\0'; 01831 if ((*p != '\0') && (*p != '/') && (*p != '>')) 01832 { 01833 /* 01834 Find tag in default attributes list. 01835 */ 01836 i=0; 01837 while ((root->attributes[i] != (char **) NULL) && 01838 (strcmp(root->attributes[i][0],tag) != 0)) 01839 i++; 01840 attribute=root->attributes[i]; 01841 } 01842 for (l=0; (*p != '\0') && (*p != '/') && (*p != '>'); l+=2) 01843 { 01844 /* 01845 Attribute. 01846 */ 01847 if (l == 0) 01848 attributes=(char **) AcquireQuantumMemory(4,sizeof(*attributes)); 01849 else 01850 attributes=(char **) ResizeQuantumMemory(attributes,(size_t) (l+4), 01851 sizeof(*attributes)); 01852 if (attributes == (char **) NULL) 01853 { 01854 (void) ThrowWizardException(exception,GetWizardModule(), 01855 ResourceError,"memory allocation failed `%s'",strerror(errno)); 01856 utf8=DestroyString(utf8); 01857 return(&root->root); 01858 } 01859 attributes[l+2]=(char *) NULL; 01860 attributes[l+1]=(char *) NULL; 01861 attributes[l]=p; 01862 p+=strcspn(p,XMLWhitespace "=/>"); 01863 if ((*p != '=') && (isspace((int) ((unsigned char) *p)) == 0)) 01864 attributes[l]=ConstantString(""); 01865 else 01866 { 01867 *p++='\0'; 01868 p+=strspn(p,XMLWhitespace "="); 01869 c=(*p); 01870 if ((c == '"') || (c == '\'')) 01871 { 01872 /* 01873 Attributes value. 01874 */ 01875 p++; 01876 attributes[l+1]=p; 01877 while ((*p != '\0') && (*p != c)) 01878 p++; 01879 if (*p != '\0') 01880 *p++='\0'; 01881 else 01882 { 01883 attributes[l]=ConstantString(""); 01884 attributes[l+1]=ConstantString(""); 01885 (void) DestroyXMLTreeAttributes(attributes); 01886 (void) ThrowWizardException(exception,GetWizardModule(), 01887 OptionWarning,"missing %c",c); 01888 utf8=DestroyString(utf8); 01889 return(&root->root); 01890 } 01891 j=1; 01892 while ((attribute != (char **) NULL) && 01893 (attribute[j] != (char *) NULL) && 01894 (strcmp(attribute[j],attributes[l]) != 0)) 01895 j+=3; 01896 attributes[l+1]=ParseEntities(attributes[l+1],root->entities, 01897 (attribute != (char **) NULL) && (attribute[j] != 01898 (char *) NULL) ? *attribute[j+2] : ' '); 01899 } 01900 attributes[l]=ConstantString(attributes[l]); 01901 } 01902 while (isspace((int) ((unsigned char) *p)) != 0) 01903 p++; 01904 } 01905 if (*p == '/') 01906 { 01907 /* 01908 Self closing tag. 01909 */ 01910 *p++='\0'; 01911 if (((*p != '\0') && (*p != '>')) || 01912 ((*p == '\0') && (terminal != '>'))) 01913 { 01914 if (l != 0) 01915 (void) DestroyXMLTreeAttributes(attributes); 01916 (void) ThrowWizardException(exception,GetWizardModule(), 01917 OptionWarning,"missing >"); 01918 utf8=DestroyString(utf8); 01919 return(&root->root); 01920 } 01921 ParseOpenTag(root,tag,attributes); 01922 (void) ParseCloseTag(root,tag,p,exception); 01923 } 01924 else 01925 { 01926 c=(*p); 01927 if ((*p == '>') || ((*p == '\0') && (terminal == '>'))) 01928 { 01929 *p='\0'; 01930 ParseOpenTag(root,tag,attributes); 01931 *p=c; 01932 } 01933 else 01934 { 01935 if (l != 0) 01936 (void) DestroyXMLTreeAttributes(attributes); 01937 (void) ThrowWizardException(exception,GetWizardModule(), 01938 OptionWarning,"missing >"); 01939 utf8=DestroyString(utf8); 01940 return(&root->root); 01941 } 01942 } 01943 } 01944 else 01945 if (*p == '/') 01946 { 01947 /* 01948 Close tag. 01949 */ 01950 tag=p+1; 01951 p+=strcspn(tag,XMLWhitespace ">")+1; 01952 c=(*p); 01953 if ((c == '\0') && (terminal != '>')) 01954 { 01955 (void) ThrowWizardException(exception,GetWizardModule(), 01956 OptionWarning,"missing >"); 01957 utf8=DestroyString(utf8); 01958 return(&root->root); 01959 } 01960 *p='\0'; 01961 if (ParseCloseTag(root,tag,p,exception) != (XMLTreeInfo *) NULL) 01962 { 01963 utf8=DestroyString(utf8); 01964 return(&root->root); 01965 } 01966 *p=c; 01967 if (isspace((int) ((unsigned char) *p)) != 0) 01968 p+=strspn(p,XMLWhitespace); 01969 } 01970 else 01971 if (strncmp(p,"!--",3) == 0) 01972 { 01973 /* 01974 Comment. 01975 */ 01976 p=strstr(p+3,"--"); 01977 if ((p == (char *) NULL) || ((*(p+=2) != '>') && (*p != '\0')) || 01978 ((*p == '\0') && (terminal != '>'))) 01979 { 01980 (void) ThrowWizardException(exception,GetWizardModule(), 01981 OptionWarning,"unclosed <!--"); 01982 utf8=DestroyString(utf8); 01983 return(&root->root); 01984 } 01985 } 01986 else 01987 if (strncmp(p,"![CDATA[",8) == 0) 01988 { 01989 /* 01990 Cdata. 01991 */ 01992 p=strstr(p,"]]>"); 01993 if (p != (char *) NULL) 01994 { 01995 p+=2; 01996 ParseCharacterContent(root,tag+8,(size_t) (p-tag-10),'c'); 01997 } 01998 else 01999 { 02000 (void) ThrowWizardException(exception,GetWizardModule(), 02001 OptionWarning,"unclosed <![CDATA["); 02002 utf8=DestroyString(utf8); 02003 return(&root->root); 02004 } 02005 } 02006 else 02007 if (strncmp(p,"!DOCTYPE",8) == 0) 02008 { 02009 /* 02010 DTD. 02011 */ 02012 for (l=0; (*p != '\0') && (((l == 0) && (*p != '>')) || 02013 ((l != 0) && ((*p != ']') || 02014 (*(p+strspn(p+1,XMLWhitespace)+1) != '>')))); 02015 l=(*p == '[') ? 1 : l) 02016 p+=strcspn(p+1,"[]>")+1; 02017 if ((*p == '\0') && (terminal != '>')) 02018 { 02019 (void) ThrowWizardException(exception,GetWizardModule(), 02020 OptionWarning,"unclosed <!DOCTYPE"); 02021 utf8=DestroyString(utf8); 02022 return(&root->root); 02023 } 02024 if (l != 0) 02025 tag=strchr(tag,'[')+1; 02026 if (l != 0) 02027 { 02028 status=ParseInternalDoctype(root,tag,(size_t) (p-tag), 02029 exception); 02030 if (status == WizardFalse) 02031 { 02032 utf8=DestroyString(utf8); 02033 return(&root->root); 02034 } 02035 p++; 02036 } 02037 } 02038 else 02039 if (*p == '?') 02040 { 02041 /* 02042 Processing instructions. 02043 */ 02044 do 02045 { 02046 p=strchr(p,'?'); 02047 if (p == (char *) NULL) 02048 break; 02049 p++; 02050 } while ((*p != '\0') && (*p != '>')); 02051 if ((p == (char *) NULL) || ((*p == '\0') && 02052 (terminal != '>'))) 02053 { 02054 (void) ThrowWizardException(exception,GetWizardModule(), 02055 OptionWarning,"unclosed <?"); 02056 utf8=DestroyString(utf8); 02057 return(&root->root); 02058 } 02059 ParseProcessingInstructions(root,tag+1,(size_t) (p-tag-2)); 02060 } 02061 else 02062 { 02063 (void) ThrowWizardException(exception,GetWizardModule(), 02064 OptionWarning,"unexpected <"); 02065 utf8=DestroyString(utf8); 02066 return(&root->root); 02067 } 02068 if ((p == (char *) NULL) || (*p == '\0')) 02069 break; 02070 *p++='\0'; 02071 tag=p; 02072 if ((*p != '\0') && (*p != '<')) 02073 { 02074 /* 02075 Tag character content. 02076 */ 02077 while ((*p != '\0') && (*p != '<')) 02078 p++; 02079 if (*p == '\0') 02080 break; 02081 ParseCharacterContent(root,tag,(size_t) (p-tag),'&'); 02082 } 02083 else 02084 if (*p == '\0') 02085 break; 02086 } 02087 utf8=DestroyString(utf8); 02088 if (root->node == (XMLTreeInfo *) NULL) 02089 return(&root->root); 02090 if (root->node->tag == (char *) NULL) 02091 { 02092 (void) ThrowWizardException(exception,GetWizardModule(),OptionWarning, 02093 "root tag missing"); 02094 return(&root->root); 02095 } 02096 (void) ThrowWizardException(exception,GetWizardModule(),OptionWarning, 02097 "unclosed tag: `%s'",root->node->tag); 02098 return(&root->root); 02099 } 02100 02101 /* 02102 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 02103 % % 02104 % % 02105 % % 02106 % N e w X M L T r e e T a g % 02107 % % 02108 % % 02109 % % 02110 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 02111 % 02112 % NewXMLTreeTag() returns a new empty xml structure for the xml-tree tag. 02113 % 02114 % The format of the NewXMLTreeTag method is: 02115 % 02116 % XMLTreeInfo *NewXMLTreeTag(const char *tag) 02117 % 02118 % A description of each parameter follows: 02119 % 02120 % o tag: the tag. 02121 % 02122 */ 02123 WizardExport XMLTreeInfo *NewXMLTreeTag(const char *tag) 02124 { 02125 static const char 02126 *predefined_entities[NumberPredefinedEntities+1] = 02127 { 02128 "lt;", "<", "gt;", ">", "quot;", """, 02129 "apos;", "'", "amp;", "&", (char *) NULL 02130 }; 02131 02132 XMLTreeRoot 02133 *root; 02134 02135 root=(XMLTreeRoot *) AcquireWizardMemory(sizeof(*root)); 02136 if (root == (XMLTreeRoot *) NULL) 02137 return((XMLTreeInfo *) NULL); 02138 (void) ResetWizardMemory(root,0,sizeof(*root)); 02139 root->root.tag=(char *) NULL; 02140 if (tag != (char *) NULL) 02141 root->root.tag=ConstantString(tag); 02142 root->node=(&root->root); 02143 root->root.content=ConstantString(""); 02144 root->entities=(char **) AcquireWizardMemory(sizeof(predefined_entities)); 02145 if (root->entities == (char **) NULL) 02146 return((XMLTreeInfo *) NULL); 02147 (void) CopyWizardMemory(root->entities,predefined_entities, 02148 sizeof(predefined_entities)); 02149 root->root.attributes=sentinel; 02150 root->attributes=(char ***) root->root.attributes; 02151 root->processing_instructions=(char ***) root->root.attributes; 02152 root->debug=IsEventLogging(); 02153 root->signature=WizardSignature; 02154 return(&root->root); 02155 } 02156 02157 /* 02158 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 02159 % % 02160 % % 02161 % % 02162 % P r u n e T a g F r o m X M L T r e e % 02163 % % 02164 % % 02165 % % 02166 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 02167 % 02168 % PruneTagFromXMLTree() prunes a tag from the xml-tree assize_t with all its 02169 % subtags. 02170 % 02171 % The format of the PruneTagFromXMLTree method is: 02172 % 02173 % XMLTreeInfo *PruneTagFromXMLTree(XMLTreeInfo *xml_info) 02174 % 02175 % A description of each parameter follows: 02176 % 02177 % o xml_info: the xml info. 02178 % 02179 */ 02180 WizardExport XMLTreeInfo *PruneTagFromXMLTree(XMLTreeInfo *xml_info) 02181 { 02182 XMLTreeInfo 02183 *node; 02184 02185 WizardAssert(ResourceDomain,xml_info != (XMLTreeInfo *) NULL); 02186 WizardAssert(ResourceDomain,(xml_info->signature == WizardSignature) || 02187 (((XMLTreeRoot *) xml_info)->signature == WizardSignature)); 02188 (void) LogWizardEvent(TraceEvent,GetWizardModule(),"..."); 02189 if (xml_info->next != (XMLTreeInfo *) NULL) 02190 xml_info->next->sibling=xml_info->sibling; 02191 if (xml_info->parent != (XMLTreeInfo *) NULL) 02192 { 02193 node=xml_info->parent->child; 02194 if (node == xml_info) 02195 xml_info->parent->child=xml_info->ordered; 02196 else 02197 { 02198 while (node->ordered != xml_info) 02199 node=node->ordered; 02200 node->ordered=node->ordered->ordered; 02201 node=xml_info->parent->child; 02202 if (strcmp(node->tag,xml_info->tag) != 0) 02203 { 02204 while (strcmp(node->sibling->tag,xml_info->tag) != 0) 02205 node=node->sibling; 02206 if (node->sibling != xml_info) 02207 node=node->sibling; 02208 else 02209 node->sibling=(xml_info->next != (XMLTreeInfo *) NULL) ? 02210 xml_info->next : node->sibling->sibling; 02211 } 02212 while ((node->next != (XMLTreeInfo *) NULL) && 02213 (node->next != xml_info)) 02214 node=node->next; 02215 if (node->next != (XMLTreeInfo *) NULL) 02216 node->next=node->next->next; 02217 } 02218 } 02219 xml_info->ordered=(XMLTreeInfo *) NULL; 02220 xml_info->sibling=(XMLTreeInfo *) NULL; 02221 xml_info->next=(XMLTreeInfo *) NULL; 02222 return(xml_info); 02223 } 02224 02225 /* 02226 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 02227 % % 02228 % % 02229 % % 02230 % S e t X M L T r e e A t t r i b u t e % 02231 % % 02232 % % 02233 % % 02234 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 02235 % 02236 % SetXMLTreeAttribute() sets the tag attributes or adds a new attribute if not 02237 % found. A value of NULL removes the specified attribute. 02238 % 02239 % The format of the SetXMLTreeAttribute method is: 02240 % 02241 % XMLTreeInfo *SetXMLTreeAttribute(XMLTreeInfo *xml_info,const char *tag, 02242 % const char *value) 02243 % 02244 % A description of each parameter follows: 02245 % 02246 % o xml_info: the xml info. 02247 % 02248 % o tag: The attribute tag. 02249 % 02250 % o value: The attribute value. 02251 % 02252 */ 02253 WizardExport XMLTreeInfo *SetXMLTreeAttribute(XMLTreeInfo *xml_info, 02254 const char *tag,const char *value) 02255 { 02256 ssize_t 02257 j; 02258 02259 register ssize_t 02260 i; 02261 02262 WizardAssert(ResourceDomain,xml_info != (XMLTreeInfo *) NULL); 02263 WizardAssert(ResourceDomain,(xml_info->signature == WizardSignature) || 02264 (((XMLTreeRoot *) xml_info)->signature == WizardSignature)); 02265 (void) LogWizardEvent(TraceEvent,GetWizardModule(),"..."); 02266 i=0; 02267 while ((xml_info->attributes[i] != (char *) NULL) && 02268 (strcmp(xml_info->attributes[i],tag) != 0)) 02269 i+=2; 02270 if (xml_info->attributes[i] == (char *) NULL) 02271 { 02272 /* 02273 Add new attribute tag. 02274 */ 02275 if (value == (const char *) NULL) 02276 return(xml_info); 02277 if (xml_info->attributes != sentinel) 02278 xml_info->attributes=(char **) ResizeQuantumMemory( 02279 xml_info->attributes,(size_t) (i+4),sizeof(*xml_info->attributes)); 02280 else 02281 { 02282 xml_info->attributes=(char **) AcquireQuantumMemory(4, 02283 sizeof(*xml_info->attributes)); 02284 if (xml_info->attributes != (char **) NULL) 02285 xml_info->attributes[1]=ConstantString(""); 02286 } 02287 if (xml_info->attributes == (char **) NULL) 02288 ThrowFatalException(ResourceFatalError, 02289 "unable to acquire string `%s'"); 02290 xml_info->attributes[i]=ConstantString(tag); 02291 xml_info->attributes[i+2]=(char *) NULL; 02292 (void) strlen(xml_info->attributes[i+1]); 02293 } 02294 /* 02295 Add new value to an existing attribute. 02296 */ 02297 for (j=i; xml_info->attributes[j] != (char *) NULL; j+=2) ; 02298 if (xml_info->attributes[i+1] != (char *) NULL) 02299 xml_info->attributes[i+1]=DestroyString(xml_info->attributes[i+1]); 02300 if (value != (const char *) NULL) 02301 { 02302 xml_info->attributes[i+1]=ConstantString(value); 02303 return(xml_info); 02304 } 02305 if (xml_info->attributes[i] != (char *) NULL) 02306 xml_info->attributes[i]=DestroyString(xml_info->attributes[i]); 02307 (void) CopyWizardMemory(xml_info->attributes+i,xml_info->attributes+i+2, 02308 (size_t) (j-i)*sizeof(*xml_info->attributes)); 02309 j-=2; 02310 xml_info->attributes=(char **) ResizeQuantumMemory(xml_info->attributes, 02311 (size_t) (j+2),sizeof(*xml_info->attributes)); 02312 if (xml_info->attributes == (char **) NULL) 02313 ThrowFatalException(ResourceFatalError,"unable to acquire string `%s'"); 02314 (void) CopyWizardMemory(xml_info->attributes[j+1]+(i/2), 02315 xml_info->attributes[j+1]+(i/2)+1,(size_t) ((j/2)-(i/2))* 02316 sizeof(*xml_info->attributes)); 02317 return(xml_info); 02318 } 02319 02320 /* 02321 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 02322 % % 02323 % % 02324 % % 02325 % S e t X M L T r e e C o n t e n t % 02326 % % 02327 % % 02328 % % 02329 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 02330 % 02331 % SetXMLTreeContent() sets the character content for the given tag and 02332 % returns the tag. 02333 % 02334 % The format of the SetXMLTreeContent method is: 02335 % 02336 % XMLTreeInfo *SetXMLTreeContent(XMLTreeInfo *xml_info, 02337 % const char *content) 02338 % 02339 % A description of each parameter follows: 02340 % 02341 % o xml_info: the xml info. 02342 % 02343 % o content: The content. 02344 % 02345 */ 02346 WizardExport XMLTreeInfo *SetXMLTreeContent(XMLTreeInfo *xml_info, 02347 const char *content) 02348 { 02349 WizardAssert(ResourceDomain,xml_info != (XMLTreeInfo *) NULL); 02350 WizardAssert(ResourceDomain,(xml_info->signature == WizardSignature) || 02351 (((XMLTreeRoot *) xml_info)->signature == WizardSignature)); 02352 (void) LogWizardEvent(TraceEvent,GetWizardModule(),"..."); 02353 if (xml_info->content != (char *) NULL) 02354 xml_info->content=DestroyString(xml_info->content); 02355 xml_info->content=(char *) ConstantString(content); 02356 return(xml_info); 02357 } 02358 02359 /* 02360 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 02361 % % 02362 % % 02363 % % 02364 % X M L T r e e I n f o T o X M L % 02365 % % 02366 % % 02367 % % 02368 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 02369 % 02370 % XMLTreeInfoToXML() converts an xml-tree to an XML string. 02371 % 02372 % The format of the XMLTreeInfoToXML method is: 02373 % 02374 % char *XMLTreeInfoToXML(XMLTreeInfo *xml_info) 02375 % 02376 % A description of each parameter follows: 02377 % 02378 % o xml_info: the xml info. 02379 % 02380 */ 02381 02382 static char *EncodePredefinedEntities(const char *source,ssize_t offset, 02383 char **destination,size_t *length,size_t *extent,WizardBooleanType pedantic) 02384 { 02385 char 02386 *canonical_content; 02387 02388 if (offset < 0) 02389 canonical_content=CanonicalXMLContent(source,pedantic); 02390 else 02391 { 02392 char 02393 *content; 02394 02395 content=AcquireString(source); 02396 content[offset]='\0'; 02397 canonical_content=CanonicalXMLContent(content,pedantic); 02398 content=DestroyString(content); 02399 } 02400 if (canonical_content == (char *) NULL) 02401 return(*destination); 02402 if ((*length+strlen(canonical_content)+MaxTextExtent) > *extent) 02403 { 02404 *extent=(*length)+strlen(canonical_content)+MaxTextExtent; 02405 *destination=(char *) ResizeQuantumMemory(*destination,*extent, 02406 sizeof(**destination)); 02407 if (*destination == (char *) NULL) 02408 return(*destination); 02409 } 02410 *length+=FormatLocaleString(*destination+(*length),*extent,"%s", 02411 canonical_content); 02412 canonical_content=DestroyString(canonical_content); 02413 return(*destination); 02414 } 02415 02416 static char *XMLTreeTagToXML(XMLTreeInfo *xml_info,char **source,size_t *length, 02417 size_t *extent,size_t start,char ***attributes) 02418 { 02419 char 02420 *content; 02421 02422 const char 02423 *attribute; 02424 02425 ssize_t 02426 j; 02427 02428 register ssize_t 02429 i; 02430 02431 size_t 02432 offset; 02433 02434 content=(char *) ""; 02435 if (xml_info->parent != (XMLTreeInfo *) NULL) 02436 content=xml_info->parent->content; 02437 offset=0; 02438 *source=EncodePredefinedEntities(content+start,(ssize_t) (xml_info->offset- 02439 start),source,length,extent,WizardFalse); 02440 if ((*length+strlen(xml_info->tag)+MaxTextExtent) > *extent) 02441 { 02442 *extent=(*length)+strlen(xml_info->tag)+MaxTextExtent; 02443 *source=(char *) ResizeQuantumMemory(*source,*extent,sizeof(*source)); 02444 if (*source == (char *) NULL) 02445 return(*source); 02446 } 02447 *length+=FormatLocaleString(*source+(*length),*extent,"<%s",xml_info->tag); 02448 for (i=0; xml_info->attributes[i]; i+=2) 02449 { 02450 attribute=GetXMLTreeAttribute(xml_info,xml_info->attributes[i]); 02451 if (attribute != xml_info->attributes[i+1]) 02452 continue; 02453 if ((*length+strlen(xml_info->attributes[i])+MaxTextExtent) > *extent) 02454 { 02455 *extent=(*length)+strlen(xml_info->attributes[i])+MaxTextExtent; 02456 *source=(char *) ResizeQuantumMemory(*source,*extent,sizeof(**source)); 02457 if (*source == (char *) NULL) 02458 return((char *) NULL); 02459 } 02460 *length+=FormatLocaleString(*source+(*length),*extent," %s=\"", 02461 xml_info->attributes[i]); 02462 (void) EncodePredefinedEntities(xml_info->attributes[i+1],-1,source,length, 02463 extent,WizardTrue); 02464 *length+=FormatLocaleString(*source+(*length),*extent,"\""); 02465 } 02466 i=0; 02467 while ((attributes[i] != (char **) NULL) && 02468 (strcmp(attributes[i][0],xml_info->tag) != 0)) 02469 i++; 02470 j=1; 02471 while ((attributes[i] != (char **) NULL) && 02472 (attributes[i][j] != (char *) NULL)) 02473 { 02474 if ((attributes[i][j+1] == (char *) NULL) || 02475 (GetXMLTreeAttribute(xml_info,attributes[i][j]) != attributes[i][j+1])) 02476 { 02477 j+=3; 02478 continue; 02479 } 02480 if ((*length+strlen(attributes[i][j])+MaxTextExtent) > *extent) 02481 { 02482 *extent=(*length)+strlen(attributes[i][j])+MaxTextExtent; 02483 *source=(char *) ResizeQuantumMemory(*source,*extent,sizeof(**source)); 02484 if (*source == (char *) NULL) 02485 return((char *) NULL); 02486 } 02487 *length+=FormatLocaleString(*source+(*length),*extent," %s=\"", 02488 attributes[i][j]); 02489 (void) EncodePredefinedEntities(attributes[i][j+1],-1,source,length,extent, 02490 WizardTrue); 02491 *length+=FormatLocaleString(*source+(*length),*extent,"\""); 02492 j+=3; 02493 } 02494 *length+=FormatLocaleString(*source+(*length),*extent,*xml_info->content ? 02495 ">" : "/>"); 02496 if (xml_info->child != (XMLTreeInfo *) NULL) 02497 *source=XMLTreeTagToXML(xml_info->child,source,length,extent,0,attributes); 02498 else 02499 *source=EncodePredefinedEntities(xml_info->content,-1,source,length,extent, 02500 WizardFalse); 02501 if ((*length+strlen(xml_info->tag)+MaxTextExtent) > *extent) 02502 { 02503 *extent=(*length)+strlen(xml_info->tag)+MaxTextExtent; 02504 *source=(char *) ResizeQuantumMemory(*source,*extent,sizeof(**source)); 02505 if (*source == (char *) NULL) 02506 return((char *) NULL); 02507 } 02508 if (*xml_info->content != '\0') 02509 *length+=FormatLocaleString(*source+(*length),*extent,"</%s>", 02510 xml_info->tag); 02511 while ((content[offset] != '\0') && (offset < xml_info->offset)) 02512 offset++; 02513 if (xml_info->ordered != (XMLTreeInfo *) NULL) 02514 content=XMLTreeTagToXML(xml_info->ordered,source,length,extent,offset, 02515 attributes); 02516 else 02517 content=EncodePredefinedEntities(content+offset,-1,source,length,extent, 02518 WizardFalse); 02519 return(content); 02520 } 02521 02522 WizardExport char *XMLTreeInfoToXML(XMLTreeInfo *xml_info) 02523 { 02524 char 02525 *xml; 02526 02527 ssize_t 02528 j, 02529 k; 02530 02531 register char 02532 *p, 02533 *q; 02534 02535 register ssize_t 02536 i; 02537 02538 size_t 02539 extent, 02540 length; 02541 02542 XMLTreeInfo 02543 *ordered, 02544 *parent; 02545 02546 XMLTreeRoot 02547 *root; 02548 02549 WizardAssert(ResourceDomain,xml_info != (XMLTreeInfo *) NULL); 02550 WizardAssert(ResourceDomain,(xml_info->signature == WizardSignature) || 02551 (((XMLTreeRoot *) xml_info)->signature == WizardSignature)); 02552 (void) LogWizardEvent(TraceEvent,GetWizardModule(),"..."); 02553 if (xml_info->tag == (char *) NULL) 02554 return((char *) NULL); 02555 xml=AcquireString((char *) NULL); 02556 length=0; 02557 extent=MaxTextExtent; 02558 root=(XMLTreeRoot *) xml_info; 02559 while (root->root.parent != (XMLTreeInfo *) NULL) 02560 root=(XMLTreeRoot *) root->root.parent; 02561 parent=(XMLTreeInfo *) NULL; 02562 if (xml_info != (XMLTreeInfo *) NULL) 02563 parent=xml_info->parent; 02564 if (parent == (XMLTreeInfo *) NULL) 02565 for (i=0; root->processing_instructions[i] != (char **) NULL; i++) 02566 { 02567 /* 02568 Pre-root processing instructions. 02569 */ 02570 for (k=2; root->processing_instructions[i][k-1]; k++) ; 02571 p=root->processing_instructions[i][1]; 02572 for (j=1; p != (char *) NULL; j++) 02573 { 02574 if (root->processing_instructions[i][k][j-1] == '>') 02575 { 02576 p=root->processing_instructions[i][j]; 02577 continue; 02578 } 02579 q=root->processing_instructions[i][0]; 02580 if ((length+strlen(p)+strlen(q)+MaxTextExtent) > extent) 02581 { 02582 extent=length+strlen(p)+strlen(q)+MaxTextExtent; 02583 xml=(char *) ResizeQuantumMemory(xml,extent,sizeof(*xml)); 02584 if (xml == (char *) NULL) 02585 return(xml); 02586 } 02587 length+=FormatLocaleString(xml+length,extent,"<?%s%s%s?>\n",q, 02588 *p != '\0' ? " " : "",p); 02589 p=root->processing_instructions[i][j]; 02590 } 02591 } 02592 ordered=(XMLTreeInfo *) NULL; 02593 if (xml_info != (XMLTreeInfo *) NULL) 02594 ordered=xml_info->ordered; 02595 xml_info->parent=(XMLTreeInfo *) NULL; 02596 xml_info->ordered=(XMLTreeInfo *) NULL; 02597 xml=XMLTreeTagToXML(xml_info,&xml,&length,&extent,0,root->attributes); 02598 xml_info->parent=parent; 02599 xml_info->ordered=ordered; 02600 if (parent == (XMLTreeInfo *) NULL) 02601 for (i=0; root->processing_instructions[i] != (char **) NULL; i++) 02602 { 02603 /* 02604 Post-root processing instructions. 02605 */ 02606 for (k=2; root->processing_instructions[i][k-1]; k++) ; 02607 p=root->processing_instructions[i][1]; 02608 for (j=1; p != (char *) NULL; j++) 02609 { 02610 if (root->processing_instructions[i][k][j-1] == '<') 02611 { 02612 p=root->processing_instructions[i][j]; 02613 continue; 02614 } 02615 q=root->processing_instructions[i][0]; 02616 if ((length+strlen(p)+strlen(q)+MaxTextExtent) > extent) 02617 { 02618 extent=length+strlen(p)+strlen(q)+MaxTextExtent; 02619 xml=(char *) ResizeQuantumMemory(xml,extent,sizeof(*xml)); 02620 if (xml == (char *) NULL) 02621 return(xml); 02622 } 02623 length+=FormatLocaleString(xml+length,extent,"\n<?%s%s%s?>",q, 02624 *p != '\0' ? " " : "",p); 02625 p=root->processing_instructions[i][j]; 02626 } 02627 } 02628 return((char *) ResizeQuantumMemory(xml,length+1,sizeof(*xml))); 02629 }