1/*
2  Copyright (C) 2000-2009 SKYRIX Software AG
3
4  This file is part of SOPE.
5
6  SOPE is free software; you can redistribute it and/or modify it under
7  the terms of the GNU Lesser General Public License as published by the
8  Free Software Foundation; either version 2, or (at your option) any
9  later version.
10
11  SOPE is distributed in the hope that it will be useful, but WITHOUT ANY
12  WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
14  License for more details.
15
16  You should have received a copy of the GNU Lesser General Public
17  License along with SOPE; see the file COPYING.  If not, write to the
18  Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
19  02111-1307, USA.
20*/
21
22#include "DOMPYXOutputter.h"
23#include "DOMDocument.h"
24#include "DOMElement.h"
25#include "common.h"
26
27@interface NGDOMPYXOutputter(Privates)
28- (void)outputNode:(id)_node to:(id)_target;
29- (void)outputNodeList:(id)_nodeList to:(id)_target;
30@end
31
32@implementation NGDOMPYXOutputter
33
34- (void)write:(NSString *)s to:(id)_target {
35#ifndef __APPLE__
36  printf("%s", [s cString]);
37#else
38  printf("%s", [s UTF8String]);
39#endif
40}
41- (BOOL)currentElementPreservesWhitespace {
42  return NO;
43}
44
45- (void)outputAttributeNode:(id<DOMAttr>)_attrNode
46  ofNode:(id<DOMNode>)_node
47  to:(id)_target
48{
49  [self write:@"A"                  to:_target];
50  [self write:[_attrNode name]      to:_target];
51  [self write:@" "                  to:_target];
52  [self write:[_attrNode nodeValue] to:_target];
53  [self write:@"\n"                 to:_target];
54}
55
56- (void)outputAttributeNodes:(id<DOMNamedNodeMap>)_nodes
57  ofNode:(id<DOMNode>)_node
58  to:(id)_target
59{
60  unsigned i, count;
61
62  if ((count = [_nodes length]) == 0)
63    return;
64
65  for (i = 0; i < count; i++) {
66    [self outputAttributeNode:[_nodes objectAtIndex:i]
67          ofNode:_node
68          to:_target];
69  }
70}
71
72- (void)outputTextNode:(id<DOMText>)_node to:(id)_target {
73  NSString *s;
74  unsigned len;
75
76  s = [_node data];
77  if ((len = [s length]) == 0)
78    return;
79
80  if ([s rangeOfString:@"\n"].length != 0) {
81    s = [[s componentsSeparatedByString:@"\n"]
82            componentsJoinedByString:@"\\n"];
83  }
84
85  [self write:@"-"  to:_target];
86  [self write:s     to:_target];
87  [self write:@"\n" to:_target];
88}
89- (void)outputCommentNode:(id<DOMComment>)_node to:(id)_target {
90  [self write:@"<!-- "     to:_target];
91  [self write:[_node data] to:_target];
92  [self write:@" -->"      to:_target];
93
94  if (![self currentElementPreservesWhitespace])
95    [self write:@"\n" to:_target];
96}
97
98- (void)outputElementNode:(id<DOMElement>)_node to:(id)_target {
99  NSString *tagName;
100  // NSString *ns;
101
102  /* needs to declare namespaces !!! */
103  tagName = [_node tagName];
104  if ([[_node prefix] length] > 0) {
105    NSString *p = [_node prefix];
106
107    p       = [p stringByAppendingString:@":"];
108    tagName = [p stringByAppendingString:tagName];
109
110    // ns = [NSString stringWithFormat:@" xmlns:%@=\"%@\"",
111    //                  [_node prefix],
112    //                  [_node namespaceURI]];
113  }
114  // else if ([[_node namespaceURI] length] > 0) {
115    // ns = [NSString stringWithFormat:@" xmlns=\"%@\"", [_node namespaceURI]];
116  // }
117  // else
118  //   ns = nil;
119
120  [self write:@"("    to:_target];
121  [self write:tagName to:_target];
122  [self write:@"\n"   to:_target];
123
124  [self outputAttributeNodes:[_node attributes] ofNode:_node to:_target];
125
126  if ([_node hasChildNodes])
127    [self outputNodeList:[_node childNodes] to:_target];
128
129  [self write:@")"    to:_target];
130  [self write:tagName to:_target];
131  [self write:@"\n"   to:_target];
132}
133
134- (void)outputCDATA:(id<DOMCharacterData>)_node to:(id)_target {
135  NSString *s;
136
137  s = [_node data];
138
139  if ([s rangeOfString:@"\n"].length != 0) {
140    /* escape newlines */
141    s = [[s componentsSeparatedByString:@"\n"]
142            componentsJoinedByString:@"\\n"];
143  }
144
145  [self write:@"-"  to:_target];
146  [self write:s     to:_target];
147  [self write:@"\n" to:_target];
148}
149
150- (void)outputPI:(id<DOMProcessingInstruction>)_node to:(id)_target {
151  [self write:@"?"           to:_target];
152  [self write:[_node target] to:_target];
153  [self write:@" "           to:_target];
154  [self write:[_node data]   to:_target];
155  [self write:@"\n"          to:_target];
156}
157
158- (void)outputNode:(id)_node to:(id)_target {
159  switch ([_node nodeType]) {
160    case DOM_ELEMENT_NODE:
161      [self outputElementNode:_node to:_target];
162      break;
163    case DOM_CDATA_SECTION_NODE:
164      [self outputCDATA:_node to:_target];
165      break;
166    case DOM_PROCESSING_INSTRUCTION_NODE:
167      [self outputPI:_node to:_target];
168      break;
169    case DOM_TEXT_NODE:
170      [self outputTextNode:_node to:_target];
171      break;
172    case DOM_COMMENT_NODE:
173      [self outputCommentNode:_node to:_target];
174      break;
175
176    default:
177      NSLog(@"cannot output node %@", _node);
178      break;
179  }
180}
181- (void)outputNodeList:(id)_nodeList to:(id)_target {
182  id       children;
183  unsigned i, count;
184
185  children = _nodeList;
186
187  for (i = 0, count = [children count]; i < count; i++)
188    [self outputNode:[children objectAtIndex:i] to:_target];
189}
190
191- (void)outputDocument:(id)_document to:(id)_target {
192  if (![_document hasChildNodes])
193    return;
194
195  NS_DURING
196    [self outputNodeList:[_document childNodes] to:_target];
197  NS_HANDLER
198#ifndef __APPLE__
199    fprintf(stderr, "%s\n", [[localException description] cString]);
200#else
201    fprintf(stderr, "%s\n", [[localException description] UTF8String]);
202#endif
203#if DEBUG
204    abort();
205#endif
206  NS_ENDHANDLER;
207}
208
209@end /* DOMPYXOutputter */
210