1
  
2
  
3
  
4
  
5
  
6
  
7
  
8
  
9
  
10
  
11
  
12
  
13
  
14
  
15
  
16
  
17
  
18
  
19
  
20
  
21
  
22
  
23
  
24
  
25
  
26
  
27
  
28
  
29
  
30
  
31
  
32
  
33
  
34
  
35
  
36
  
37
  
38
  
39
  
40
  
41
  
42
  
43
  
44
  
45
  
46
  
47
  
48
  
49
  
50
  
51
  
52
  
53
  
54
  
55
  
56
  
57
  
58
  
59
  
60
  
61
  
62
  
63
  
64
  
65
  
66
  
67
  
68
  
69
  
70
  
71
  
72
  
73
  
74
  
75
  
76
  
77
  
78
  
79
  
80
  
81
  
82
  
83
  
84
  
85
  
86
  
87
  
88
  
89
  
90
  
91
  
92
  
#pike __REAL_VERSION__ 
 
inherit Parser._parser.XML; 
 
//! XML parsing made easy. 
//! 
//! @returns 
//!   A hierarchical structure of nested mappings and arrays representing the 
//!   XML structure starting at @expr{rootnode@} using a minimal depth. 
//! 
//! @mapping 
//!   @member string "" 
//!     The text content of the node. 
//!   @member mapping "/" 
//!     The arguments on this node. 
//!   @member string "..." 
//!     The text content of a simple subnode. 
//!   @member array "..." 
//!     A list of subnodes. 
//!   @member mapping "..." 
//!     A complex subnode (recurse). 
//! @endmapping 
//! 
//! @example 
//!   @code 
//!   Parser.XML.node_to_struct(Parser.XML.NSTree.parse_input("<foo>bar</foo>")); 
//!   @endcode 
mapping(string:string|array|mapping) 
 node_to_struct(.NSTree.NSNode|.Tree.Node rootnode) { 
  return low_node_to_struct(rootnode)[1]; 
} 
 
private array low_node_to_struct(.NSTree.NSNode|.Tree.Node n) { 
  array|string|mapping ret = ([]); 
  { 
    mapping m = n->get_attributes(); 
    { 
      mapping n = n->get_short_attributes(); 
      if (n) 
        if (m) 
          m += n; 
        else 
          m = n; 
    } 
    if (m && sizeof(m)) { 
      string ns, value; 
      foreach (({"type", "base", "element"}); ; string atn) { 
        if (m[atn] && 2 == sscanf(m[atn], "%s:%s", ns, value)) 
          m[atn] = ({n->get_defined_nss()[ns], value}); 
      } 
      ret["/"] = m; 
    } 
  } 
  string text = n->get_text(); 
  if (sizeof(text)) 
    if (stringp(ret)) 
      ret += text; 
    else if (sizeof(ret)) 
      ret[""] = text; 
    else 
      ret = text; 
  else 
    foreach (n->get_children();; object child) { 
      mixed r = low_node_to_struct(child); 
      text = r[0]; 
      mixed v = stringp(ret)||arrayp(ret) ? ret : ret[text]; 
      r = r[1]; 
      if (!sizeof(text)) 
        if (stringp(ret)) 
          ret += r; 
        else if (arrayp(ret)) 
          ret += ({r}); 
        else if (mappingp(ret) && ret["/"]) 
          ret[""] = r; 
        else if (sizeof(ret)) 
          ret = ({ret, r}); 
        else 
          ret = r; 
      else if (arrayp(ret)) 
        ret += ({ ([text:r]) }); 
      else if (stringp(ret)) 
        ret = ({ ret, ([text:r]) }); 
      else if (arrayp(v)) 
        ret[text] += ({r}); 
      else 
        ret[text] = zero_type(v) ? r : ({v, r}); 
    } 
  return ({n->get_full_name(), sizeof(ret) ? ret : ""}); 
}