static int raptor_xml_writer_start_element_common(raptor_xml_writer* xml_writer, raptor_xml_element* element, int auto_empty) { raptor_iostream* iostr = xml_writer->iostr; raptor_namespace_stack *nstack = xml_writer->nstack; int depth = xml_writer->depth; int auto_indent = XML_WRITER_AUTO_INDENT(xml_writer); int xml_version = XML_WRITER_XML_VERSION(xml_writer); struct nsd *nspace_declarations = NULL; size_t nspace_declarations_count = 0; unsigned int i; /* max is 1 per element and 1 for each attribute + size of declared */ if(nstack) { int nspace_max_count = element->attribute_count+1; if(element->declared_nspaces) nspace_max_count += raptor_sequence_size(element->declared_nspaces); nspace_declarations = (struct nsd*)RAPTOR_CALLOC(nsdarray, nspace_max_count, sizeof(struct nsd)); if(!nspace_declarations) return 1; } if(element->name->nspace) { if(nstack && !raptor_namespaces_namespace_in_scope(nstack, element->name->nspace)) { nspace_declarations[0].declaration= raptor_namespace_format_as_xml(element->name->nspace, &nspace_declarations[0].length); if(!nspace_declarations[0].declaration) goto error; nspace_declarations[0].nspace = element->name->nspace; nspace_declarations_count++; } } if(element->attributes) { for(i = 0; i < element->attribute_count; i++) { /* qname */ if(element->attributes[i]->nspace) { if(nstack && !raptor_namespaces_namespace_in_scope(nstack, element->attributes[i]->nspace) && element->attributes[i]->nspace != element->name->nspace) { /* not in scope and not same as element (so already going to be declared)*/ unsigned int j; int declare_me = 1; /* check it wasn't an earlier declaration too */ for(j = 0; j < nspace_declarations_count; j++) if(nspace_declarations[j].nspace == element->attributes[j]->nspace) { declare_me = 0; break; } if(declare_me) { nspace_declarations[nspace_declarations_count].declaration= raptor_namespace_format_as_xml(element->attributes[i]->nspace, &nspace_declarations[nspace_declarations_count].length); if(!nspace_declarations[nspace_declarations_count].declaration) goto error; nspace_declarations[nspace_declarations_count].nspace = element->attributes[i]->nspace; nspace_declarations_count++; } } } } } if(nstack && element->declared_nspaces && raptor_sequence_size(element->declared_nspaces) > 0) { for(i = 0; i< (unsigned int)raptor_sequence_size(element->declared_nspaces); i++) { raptor_namespace* nspace = (raptor_namespace*)raptor_sequence_get_at(element->declared_nspaces, i); unsigned int j; int declare_me = 1; /* check it wasn't an earlier declaration too */ for(j = 0; j < nspace_declarations_count; j++) if(nspace_declarations[j].nspace == nspace) { declare_me = 0; break; } if(declare_me) { nspace_declarations[nspace_declarations_count].declaration= raptor_namespace_format_as_xml(nspace, &nspace_declarations[nspace_declarations_count].length); if(!nspace_declarations[nspace_declarations_count].declaration) goto error; nspace_declarations[nspace_declarations_count].nspace = nspace; nspace_declarations_count++; } } } raptor_iostream_write_byte('<', iostr); if(element->name->nspace && element->name->nspace->prefix_length > 0) { raptor_iostream_counted_string_write((const char*)element->name->nspace->prefix, element->name->nspace->prefix_length, iostr); raptor_iostream_write_byte(':', iostr); } raptor_iostream_counted_string_write((const char*)element->name->local_name, element->name->local_name_length, iostr); /* declare namespaces */ if(nspace_declarations_count) { /* sort them into the canonical order */ qsort((void*)nspace_declarations, nspace_declarations_count, sizeof(struct nsd), raptor_xml_writer_nsd_compare); /* add them */ for(i = 0; i < nspace_declarations_count; i++) { if(auto_indent && nspace_declarations_count > 1) { /* indent xmlns namespace attributes */ raptor_xml_writer_newline(xml_writer); xml_writer->depth++; raptor_xml_writer_indent(xml_writer); xml_writer->depth--; } raptor_iostream_write_byte(' ', iostr); raptor_iostream_counted_string_write((const char*)nspace_declarations[i].declaration, nspace_declarations[i].length, iostr); RAPTOR_FREE(cstring, nspace_declarations[i].declaration); nspace_declarations[i].declaration = NULL; if(raptor_namespace_stack_start_namespace(nstack, (raptor_namespace*)nspace_declarations[i].nspace, depth)) goto error; } } if(element->attributes) { for(i = 0; i < element->attribute_count; i++) { raptor_iostream_write_byte(' ', iostr); if(element->attributes[i]->nspace && element->attributes[i]->nspace->prefix_length > 0) { raptor_iostream_counted_string_write((char*)element->attributes[i]->nspace->prefix, element->attributes[i]->nspace->prefix_length, iostr); raptor_iostream_write_byte(':', iostr); } raptor_iostream_counted_string_write((const char*)element->attributes[i]->local_name, element->attributes[i]->local_name_length, iostr); raptor_iostream_counted_string_write("=\"", 2, iostr); raptor_xml_escape_string_any_write(element->attributes[i]->value, element->attributes[i]->value_length, '"', xml_version, iostr); raptor_iostream_write_byte('"', iostr); } } if(!auto_empty) raptor_iostream_write_byte('>', iostr); if(nstack) RAPTOR_FREE(stringarray, nspace_declarations); return 0; /* Clean up nspace_declarations on error */ error: for(i = 0; i < nspace_declarations_count; i++) { if(nspace_declarations[i].declaration) RAPTOR_FREE(cstring, nspace_declarations[i].declaration); } if(nspace_declarations) RAPTOR_FREE(stringarray, nspace_declarations); return 1; }
/** * raptor_xml_element_write: * @element: XML element to format * @nstack: Namespace stack context to use in formatting * @is_empty: non-0 if element is empty * @is_end: non-0 if this is an end element (else is a start element) * @depth: XML element depth * @iostr: iostream object * * Write a formatted XML element to a #raptor_iostream * * Return value: non-0 on failure */ int raptor_xml_element_write(raptor_xml_element *element, raptor_namespace_stack *nstack, int is_empty, int is_end, int depth, raptor_iostream* iostr) { struct nsd *nspace_declarations = NULL; size_t nspace_declarations_count = 0; unsigned int i; /* max is 1 per element and 1 for each attribute + size of declared */ if(nstack) { int nspace_max_count = element->attribute_count+1; if(element->declared_nspaces) nspace_max_count += raptor_sequence_size(element->declared_nspaces); nspace_declarations = RAPTOR_CALLOC(struct nsd*, nspace_max_count, sizeof(struct nsd)); } if(element->name->nspace) { if(!is_end && nstack && !raptor_namespaces_namespace_in_scope(nstack, element->name->nspace)) { nspace_declarations[0].declaration= raptor_namespace_format_as_xml(element->name->nspace, &nspace_declarations[0].length); nspace_declarations[0].nspace = element->name->nspace; nspace_declarations_count++; } } if(!is_end && element->attributes) { for(i = 0; i < element->attribute_count; i++) { /* qname */ if(element->attributes[i]->nspace) { if(nstack && !raptor_namespaces_namespace_in_scope(nstack, element->attributes[i]->nspace) && element->attributes[i]->nspace != element->name->nspace) { /* not in scope and not same as element (so already going to be declared)*/ unsigned int j; int declare_me = 1; /* check it wasn't an earlier declaration too */ for(j = 0; j < nspace_declarations_count; j++) if(nspace_declarations[j].nspace == element->attributes[j]->nspace) { declare_me = 0; break; } if(declare_me) { nspace_declarations[nspace_declarations_count].declaration= raptor_namespace_format_as_xml(element->attributes[i]->nspace, &nspace_declarations[nspace_declarations_count].length); nspace_declarations[nspace_declarations_count].nspace = element->attributes[i]->nspace; nspace_declarations_count++; } } } } } if(!is_end && nstack && element->declared_nspaces && raptor_sequence_size(element->declared_nspaces) > 0) { for(i = 0; i< (unsigned int)raptor_sequence_size(element->declared_nspaces); i++) { raptor_namespace* nspace = (raptor_namespace*)raptor_sequence_get_at(element->declared_nspaces, i); unsigned int j; int declare_me = 1; /* check it wasn't an earlier declaration too */ for(j = 0; j < nspace_declarations_count; j++) if(nspace_declarations[j].nspace == nspace) { declare_me = 0; break; } if(declare_me) { nspace_declarations[nspace_declarations_count].declaration= raptor_namespace_format_as_xml(nspace, &nspace_declarations[nspace_declarations_count].length); nspace_declarations[nspace_declarations_count].nspace = nspace; nspace_declarations_count++; } } } raptor_iostream_write_byte('<', iostr); if(is_end) raptor_iostream_write_byte('/', iostr); if(element->name->nspace && element->name->nspace->prefix_length > 0) { raptor_iostream_counted_string_write((const char*)element->name->nspace->prefix, element->name->nspace->prefix_length, iostr); raptor_iostream_write_byte(':', iostr); } raptor_iostream_counted_string_write((const char*)element->name->local_name, element->name->local_name_length, iostr); /* declare namespaces */ if(nspace_declarations_count) { /* sort them into the canonical order */ qsort((void*)nspace_declarations, nspace_declarations_count, sizeof(struct nsd), raptor_nsd_compare); /* add them */ for(i = 0; i < nspace_declarations_count; i++) { raptor_iostream_write_byte(' ', iostr); raptor_iostream_counted_string_write((const char*)nspace_declarations[i].declaration, nspace_declarations[i].length, iostr); RAPTOR_FREE(char*, nspace_declarations[i].declaration); nspace_declarations[i].declaration = NULL; raptor_namespace_stack_start_namespace(nstack, (raptor_namespace*)nspace_declarations[i].nspace, depth); } } if(!is_end && element->attributes) { for(i = 0; i < element->attribute_count; i++) { raptor_iostream_write_byte(' ', iostr); if(element->attributes[i]->nspace && element->attributes[i]->nspace->prefix_length > 0) { raptor_iostream_counted_string_write((char*)element->attributes[i]->nspace->prefix, element->attributes[i]->nspace->prefix_length, iostr); raptor_iostream_write_byte(':', iostr); } raptor_iostream_counted_string_write((const char*)element->attributes[i]->local_name, element->attributes[i]->local_name_length, iostr); raptor_iostream_counted_string_write("=\"", 2, iostr); raptor_xml_escape_string_write(element->attributes[i]->value, element->attributes[i]->value_length, '"', iostr); raptor_iostream_write_byte('"', iostr); } } if(is_empty) raptor_iostream_write_byte('/', iostr); raptor_iostream_write_byte('>', iostr); if(nstack) RAPTOR_FREE(stringarray, nspace_declarations); return 0; }