Available in:
Apps (win)
Apps (char)
Reportwriter
RPC
Standalone PL
X
X
X
X
X
expr xml(opt[,parm]) int opt expr parm
| opt | parm | function |
| xml_attr | attribute name | Returns the value of the specified attribute. If the attribute is not found, then it returns NULL. |
| xml_data | N/A | Returns the current XML data value as a character string. If an error has occurred in any other XML function, then the error message can be retrieved using xml(xml_data). |
| xml_endtag | N/A | Returns true if the XML stream is at the end of a tag. |
| xml_esc | string | Returns a string with string's special HTML characters converted to HTML entities (see xml_unesc). |
| xml_free | N/A | Frees all resources associated with the XML system. |
| xml_init | Any valid file source | Initializes the XML system using the specified XML stream. |
| xml_name | N/A | Returns the current XML tag as a character string. |
| xml_next | N/A | Moves to the next XML tag. The entire attribute string is available using xml(xml_data). Returns either the tag code value if xml(xml_tags,list) was called, (-1) if no tags were sent, or NULL if an error occurred. If the return code is NULL, use xml(xml_data) to retrieve the error message. |
| xml_tags | list of tag/value pairs | Sends a list of valid XML tags to the XML system in the form of a two column list. The first column is the tag and the second column is its code value. |
| xml_unesc | string | Returns a string with string's HTML entities converted to special HTML characters (see xml_esc). |
| xml_value | N/A | Returns the current uninterpreted data from the XML stream. If it returns NULL, then if xml(xml_endtag) returns true, the XML stream is empty; otherwise the XML stream is positioned at a new XML tag. |
/******************************************************************************
** Convert generic XML file to internal list format
**
** parm.0 - XML file
** parm.1 - Internal list file
**
** Format of list: col0: tag name
** col1: attributes (NULL if none)
** col2: NULL no data (<..../>)
** Char datatype then string data
** List datatype then sub-tree
**
*******************************************************************************/
#trigger next_element
/******************************************************************************
** Get next tag element
*******************************************************************************/
{
int rc,end;
rc = xml(xml_next);
if (!rc) error(xml(xml_data));
if (rc < (-1)) end = true;
else end = xml(xml_endtag);
return([xml(xml_name),end,xml(xml_data)]);
} /* next_element */
#trigger dive
/******************************************************************************
** Process XML
*******************************************************************************/
{
int i;
char val[500],attr[1000];
local int end;
local int level = parm.0;
local char s[200] = "";
local char tag[100],exit_tag[100] = parm.1;
for (i=level;i;i--) s = s ^^ " ";
while (true) {
[tag,end,attr] = next_element();
if (end) {
if (tag == exit_tag) return;
list_mod(parm.2,1,tag,attr,NULL);
continue;
}
val = xml(xml_value);
val = ltrim(rtrim(val,G.sc),G.sc);
if (xml(xml_endtag) && (tag == xml(xml_name))) {
list_mod(parm.2,1,tag,attr,val);
xml(xml_next); /* eat */
if (tag == exit_tag) return;
}
else {
list_mod(parm.2,1,tag,attr,list_open("20 30 20",0));
dive(level+1,tag,list_curr(parm.2,2));
if (!exit_tag) return;
}
}
} /* dive */
#trigger
/******************************************************************************
** Main
*******************************************************************************/
{
char sc[3] = chr(10,13,32); /* trim chars */
list LL;
xml(xml_init,parm.0);
LL = list_open("20 30 20",0);
dive(0,NULL,LL);
list_file(LL,parm.1,"x");
xml(xml_free);
}
Convert an internal XML list to a generic XML file.
/******************************************************************************
** Convert internal XML list to generic XML file
**
** parm.0 - file with list
**
** Format of list: col0: tag name
** col1: attributes (NULL if none)
** col2: NULL no data (<..../>)
** Char datatype then string data
** List datatype then sub-tree
**
*******************************************************************************/
#trigger dive
/******************************************************************************
** Process a list
*******************************************************************************/
{
local int i;
local char tag[100];
char s[1000],attr[500];
for (i=list_rows(parm.0);i;i--) {
tag = list_curr(parm.0,0);
attr = list_curr(parm.0,1);
s = "<" ^^ tag;
if (attr) s = s ^^ " " ^^ attr;
if (list_curr(parm.0,2) == NULL) printf(s ^^ "/>");
else if (datatype(list_curr(parm.0,2)) == "C")
printf(s ^^ ">" ^^ translate(translate(translate(translate(translate(
list_curr(parm.0,2),
"&","&"),
"<","<"),
">",">"),
"'","'"),
"""",""") ^^ "</" ^^ tag ^^ ">");
else { /* a sub-list */
printf(s ^^ ">");
dive(list_curr(parm.0,2));
printf("</" ^^ tag ^^ ">");
} /* a sub-list */
list_next(parm.0);
}
} /* dive */
#trigger
/******************************************************************************
** Main
*******************************************************************************/
{
list LL;
LL = list_open(parm.0,999999);
dive(LL);
}
Convert special HTML characters to HTML entities and back again:
{
char buf[100];
buf = xml(xml_esc,"<data wb='www.trifox.com?cow=42&moo=53'>");
printf(buf);
buf = xml(xml_unesc,buf);
printf(buf);
}
returns
<data wb='www.trifox.com?cow=42&moo=53'> <data wb='www.trifox.com?cow=42&moo=53'>