XML/Output
![Task](http://static.miraheze.org/rosettacodewiki/thumb/b/ba/Rcode-button-task-crushed.png/64px-Rcode-button-task-crushed.png)
You are encouraged to solve this task according to the task description, using any language you may know.
Create a function that takes a list of character names and a list of corresponding remarks and returns an XML doccument of <Character>
elements each with a name attributes and each enclosing its remarks. All <Character>
elements are to be enclosed in turn, in an outer <CharacterRemarks>
element.
As an example, calling the function with the three names of:
April Tam O'Shanter Emily
And three remarks of:
Bubbly: I'm > Tam and <= Emily Burns: "When chapman billies leave the street ..." Short & shrift
Should produce the XML (but not necessarily with the indentation):
<CharacterRemarks> <Character name="April">Bubbly: I'm > Tam and <= Emily</Character> <Character name="Tam O'Shanter" >Burns: "When chapman billies leave the street ..."</Character> <Character name="Emily">Short & shrift</Character> </CharacterRemarks>
The document may include an <?xml?> declaration and document type declaration, but these are optional. If attempting this task by direct string manipulation, the implementation must include code to perform entity substitution for the characters that have entities defined in the XML 1.0 specification.
Note: the example is chosen to show correct escaping of XML strings Note too that although the task is written to take two lists of corresponding data, a single mapping/hash/dictionary of names to remarks is also acceptable
C
<lang c>#include <stdio.h>
- include <stdlib.h>
- include <string.h>
- include <libxml/parser.h>
- include <libxml/tree.h>
char *names[] = {
"April", "Bob", "Chad", "Dave", "Emily", NULL
};
int main() {
xmlDoc *doc = NULL; xmlNode *root = NULL, *node; char **next;
doc = xmlNewDoc("1.0"); root = xmlNewNode(NULL, "Students"); xmlDocSetRootElement(doc, root);
for(next = names; *next != NULL; next++) { node = xmlNewNode(NULL, "Student"); (void)xmlNewProp(node, "Name", *next); xmlAddChild(root, node); }
xmlElemDump(stdout, doc, root);
xmlFreeDoc(doc); xmlCleanupParser(); return EXIT_SUCCESS;
}</lang>
OCaml
<lang ocaml>
- #directory "+site-lib/xml-light" (* or maybe just "+xml-light" *) ;;
- #load "xml-light.cma" ;;
- let students = ["April"; "Bob"; "Chad"; "Dave"; "Emily"] in
let tags_students = List.map (fun name -> Xml.Element ("Student", [("Name", name)], []) ) students in print_endline ( Xml.to_string_fmt (Xml.Element ("Students", [], tags_students))) ;;
<Students>
<Student Name="April"/> <Student Name="Bob"/> <Student Name="Chad"/> <Student Name="Dave"/> <Student Name="Emily"/>
</Students> - : unit = () </lang>
Perl
<lang perl>#! /usr/bin/perl use strict; use XML::Mini::Document;
my @students = ( "April", "Bob", "Chad", "Dave", "Emily" );
my $doc = XML::Mini::Document->new(); my $root = $doc->getRoot(); my $studs = $root->createChild("Students"); foreach my $s (@students) {
my $stud = $studs->createChild("Student"); $stud->attribute("Name", $s);
} print $doc->toString();
exit 0;</lang>
Python
Normal output is all one line of XML, the .replace(...) makes it more readable. <lang python>>>> from xml.etree import ElementTree as ET >>> from itertools import izip >>> def characterstoxml(names, remarks): root = ET.Element("CharacterRemarks") for name, remark in izip(names, remarks): c = ET.SubElement(root, "Character", {'name': name}) c.text = remark return ET.tostring(root)
>>> print characterstoxml( names = ["April", "Tam O'Shanter", "Emily"], remarks = [ "Bubbly: I'm > Tam and <= Emily", 'Burns: "When chapman billies leave the street ..."', 'Short & shrift' ] ).replace('><','>\n<')</lang> Gives the output:
<CharacterRemarks> <Character name="April">Bubbly: I'm > Tam and <= Emily</Character> <Character name="Tam O'Shanter">Burns: "When chapman billies leave the street ..."</Character> <Character name="Emily">Short & shrift</Character> </CharacterRemarks>
Ruby
<lang ruby>require 'rexml/document' include REXML
doc = Document.new root = doc.add_element("Students")
%w(April Bob Chad David Emily).each do |name|
root.add_element("Student", {'Name' => name})
end
- output with no added whitespace
doc.write print "\n\n"
- to reproduce the sample output of the task
doc.write($stdout, 2, false, true)</lang>
produces
<Students><Student Name='April'/><Student Name='Bob'/><Student Name='Chad'/><Student Name='David'/><Student Name='Emily'/></Students> <Students> <Student Name='April' /> <Student Name='Bob' /> <Student Name='Chad' /> <Student Name='David' /> <Student Name='Emily' /> </Students>
Slate
<lang slate> slate[1]> [ | writer |
writer: (Xml Writer newOn: new writer). writer inTag: 'Students' do: [ |:w| {'April'. 'Bob'. 'Chad'. 'Dave'. 'Emily'} do: [|:name| w emitTag: 'Student' &attributes: {'Name' -> name}]. ]. writer contents
] do.
'<Students><Student Name="April" /><Student Name="Bob" /><Student Name="Chad" /><Student Name="Dave" /><Student Name="Emily" /></Students>'
</lang>
Tcl
Using only Tcl string manipulation: <lang Tcl> proc < {name attl args} {
set res <$name foreach {att val} $attl { append res " $att='[string map {' '} $val]'" } if {[llength $args]} { append res > foreach a $args { append res \n$a } append res </$name> } else {append res />} return $res
} set cmd {< Students {}} foreach XXX {April Bob Chad Dave Emily O'Connor} {
append cmd " \[< Student {Name $XXX}\]"
} puts [eval $cmd]</lang>
produces
<Students> <Student Name='April'/> <Student Name='Bob'/> <Student Name='Chad'/> <Student Name='Dave'/> <Student Name='Emily'/> <Student Name='O'Connor'/></Students>
Using
<lang tcl>package require tdom set xml [dom createDocument Students] foreach name {April Bob Chad Dave Emily} {
set element [$xml createElement Student] $element setAttribute Name $name [$xml documentElement] appendChild $element
} $xml asXML</lang>
<Students> <Student Name="April"/> <Student Name="Bob"/> <Student Name="Chad"/> <Student Name="Dave"/> <Student Name="Emily"/> </Students>
Using
<lang tcl>package require dom set xml [dom::DOMImplementation create] set root [dom::document createElement $xml Students] foreach name {April Bob Chad Dave Emily} {
set element [dom::document createElement $root Student] dom::element setAttribute $element Name $name
} dom::DOMImplementation serialize $xml</lang>
<?xml version='1.0'?> <!DOCTYPE Students> <Students><Student Name="April"/><Student Name="Bob"/><Student Name="Chad"/><Student Name="Dave"/><Student Name="Emily"/></Students>
Visual Basic .NET
<lang vbnet>Dim names As String() = New String() {"April", "Bob", "Chad", "Dave", "Emily"}
Dim xml = <Students>
<%= From s In names Select <Student Name=<%= s %>/> %> </Students>
Console.WriteLine(xml)</lang>
- Programming Tasks
- XML
- C
- C examples needing attention
- Examples needing attention
- LibXML
- OCaml
- OCaml examples needing attention
- Perl
- Perl examples needing attention
- Python
- Ruby
- Ruby examples needing attention
- REXML
- Slate
- Slate examples needing attention
- Tcl
- Tcl examples needing attention
- TDOM
- TclXML
- Visual Basic .NET
- Visual Basic .NET examples needing attention