XML/Output: Difference between revisions

From Rosetta Code
< XML
Content added Content deleted
(Vedit macro language added)
(Updated to meet requirements)
Line 197: Line 197:


=={{header|Slate}}==
=={{header|Slate}}==
{{needs-review|Slate}}


<lang 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.


lobby define: #remarks -> (
{'April' -> 'Bubbly: I\'m > Tam and <= Emily'.
'Tam O\'Shanter' -> 'Burns: "When chapman billies leave the street ..."'.
'Emily' -> 'Short & shrift'.
} as: Dictionary).


define: #writer -> (Xml Writer newOn: '' new writer).
'<Students><Student Name="April" /><Student Name="Bob" /><Student Name="Chad" /><Student Name="Dave" /><Student Name="Emily" /></Students>'
writer inTag: 'CharacterRemarks' do:
[| :w |
lobby remarks keysAndValuesDo:
[| :name :remark | w inTag: 'Character' do: [| :w | w ; remark] &attributes: {'name' -> name}].
].

inform: writer contents

<CharacterRemarks><Character name="Emily">Short &amp; shrift</Character><Character name="Tam O'Shanter">Burns: "When chapman billies leave the street ..."</Character><Character name="April">Bubbly: I&quot;m &gt; Tam and &lt;= Emily</Character></CharacterRemarks><CharacterRemarks><Character name="Emily">Short &amp; shrift</Character><Character name="Tam O'Shanter">Burns: "When chapman billies leave the street ..."</Character><Character name="April">Bubbly: I&apos;m &gt; Tam and &lt;= Emily</Character></CharacterRemarks><CharacterRemarks><Character name="Emily">Short &amp; shrift</Character><Character name="Tam O'Shanter">Burns: "When chapman billies leave the street ..."</Character><Character name="April">Bubbly: I&apos;m &gt; Tam and &lt;= Emily</Character></CharacterRemarks>
</lang>
</lang>



Revision as of 21:43, 11 June 2009

Task
XML/Output
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 &gt; Tam and &lt;= Emily</Character>
    <Character name="Tam O&apos;Shanter"
            >Burns: &quot;When chapman billies leave the street ...&quot;</Character>
    <Character name="Emily">Short &amp; 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

This example may be incorrect due to a recent change in the task requirements or a lack of testing. Please verify it and remove this message. If the example does not match the requirements or does not work, replace this message with Template:incorrect or fix the code yourself.
Library: libXML

<lang c>#include <stdio.h>

  1. include <stdlib.h>
  2. include <string.h>
  3. include <libxml/parser.h>
  4. 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>

F#

#light

open System.Xml
type Character = {name : string; comment : string }

let data = [
    { name = "April"; comment = "Bubbly: I'm > Tam and <= Emily"}
    { name = "Tam O'Shanter"; comment = "Burns: \"When chapman billies leave the street ...\""}
    { name = "Emily"; comment = "Short & shrift"} ]

let doxml (characters : Character list) =
    let doc = new XmlDocument()
    let root = doc.CreateElement("CharacterRemarks")
    doc.AppendChild root |> ignore
    Seq.iter (fun who ->
             let node = doc.CreateElement("Character")
             node.SetAttribute("name", who.name)
             doc.CreateTextNode(who.comment) 
             |> node.AppendChild |> ignore
             root.AppendChild node |> ignore
             ) characters
    doc.OuterXml
<CharacterRemarks>
 <Character name="April">Bubbly: I'm &gt; Tam and &lt;= Emily</Character>
 <Character name="Tam O'Shanter">Burns: "When chapman billies leave the street ..."</Character>
 <Character name="Emily">Short &amp; shrift</Character>
</CharacterRemarks>

OCaml

This example may be incorrect due to a recent change in the task requirements or a lack of testing. Please verify it and remove this message. If the example does not match the requirements or does not work, replace this message with Template:incorrect or fix the code yourself.

<lang ocaml>

  1. #directory "+site-lib/xml-light" (* or maybe just "+xml-light" *) ;;
  1. #load "xml-light.cma" ;;
  1. 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

This example may be incorrect due to a recent change in the task requirements or a lack of testing. Please verify it and remove this message. If the example does not match the requirements or does not work, replace this message with Template:incorrect or fix the code yourself.
Library: XML::MiniMini

<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 &gt; Tam and &lt;= Emily</Character>
<Character name="Tam O&apos;Shanter">Burns: "When chapman billies leave the street ..."</Character>
<Character name="Emily">Short &amp; shrift</Character>
</CharacterRemarks>

Ruby

The

Library: REXML

library handles character mapping when adding attributes and text.

<lang ruby>require 'rexml/document' include REXML

remarks = {

 %q(April)         => %q(Bubbly: I'm > Tam and <= Emily),
 %q(Tam O'Shanter) => %q(Burns: "When chapman billies leave the street ..."),
 %q(Emily)         => %q(Short & shrift),

}

doc = Document.new root = doc.add_element("CharacterRemarks")

remarks.each do |name, remark|

 root.add_element("Character", {'Name' => name}).add_text(remark)

end

  1. output with indentation

doc.write($stdout, 2)</lang>

produces

<CharacterRemarks>
  <Character Name='Emily'>
    Short &amp; shrift
  </Character>
  <Character Name='Tam O&apos;Shanter'>
    Burns: &quot;When chapman billies leave the street ...&quot;
  </Character>
  <Character Name='April'>
    Bubbly: I&apos;m &gt; Tam and &lt;= Emily
  </Character>
</CharacterRemarks>

Slate

<lang slate>

lobby define: #remarks -> ( {'April' -> 'Bubbly: I\'m > Tam and <= Emily'. 'Tam O\'Shanter' -> 'Burns: "When chapman billies leave the street ..."'. 'Emily' -> 'Short & shrift'. } as: Dictionary).

define: #writer -> (Xml Writer newOn: new writer). writer inTag: 'CharacterRemarks' do:

 [| :w |
  lobby remarks keysAndValuesDo:
    [| :name :remark | w inTag: 'Character' do: [| :w | w ; remark] &attributes: {'name' -> name}].
  ].

inform: writer contents

<CharacterRemarks><Character name="Emily">Short & shrift</Character><Character name="Tam O'Shanter">Burns: "When chapman billies leave the street ..."</Character><Character name="April">Bubbly: I"m > Tam and <= Emily</Character></CharacterRemarks><CharacterRemarks><Character name="Emily">Short & shrift</Character><Character name="Tam O'Shanter">Burns: "When chapman billies leave the street ..."</Character><Character name="April">Bubbly: I'm > Tam and <= Emily</Character></CharacterRemarks><CharacterRemarks><Character name="Emily">Short & shrift</Character><Character name="Tam O'Shanter">Burns: "When chapman billies leave the street ..."</Character><Character name="April">Bubbly: I'm > Tam and <= Emily</Character></CharacterRemarks> </lang>

Tcl

Using only Tcl string manipulation

<lang Tcl>proc xquote string {

   list [string map {' ' \" " < > > < & &} $string]

} proc < {name attl args} {

   set res <$name
   foreach {att val} $attl {
       append res " $att='$val'"
   }
   if {[llength $args]} {
       append res >
       set sep ""
       foreach a $args {
           append res $sep $a
           set sep \n
       } 
       append res </$name>
   } else {append res />}
   return $res

} set cmd {< CharacterRemarks {}} foreach {name comment} {

   April "Bubbly: I'm > Tam and <= Emily"
   "Tam O'Shanter" "Burns: \"When chapman billies leave the street ...\""
   Emily "Short & shrift"

} {

   append cmd " \[< Character {Name [xquote $name]} [xquote $comment]\]"

} puts [eval $cmd]</lang>

produces

<CharacterRemarks><Character Name='April'>Bubbly: I&apos;m &lt; Tam and &gt;= Emily</Character>
<Character Name='Tam O&apos;Shanter'>Burns: &quot;When chapman billies leave the street ...&quot;</Character>
<Character Name='Emily'>Short &amp; shrift</Character></CharacterRemarks>

Working with DOM trees

Using

Library: tDOM

<lang tcl>package require tdom set xml [dom createDocument CharacterRemarks] foreach {name comment} {

   April "Bubbly: I'm > Tam and <= Emily"
   "Tam O'Shanter" "Burns: \"When chapman billies leave the street ...\""
   Emily "Short & shrift"

} {

   set elem [$xml createElement Character]
   $elem setAttribute name $name
   $elem appendChild [$xml createTextNode $comment]
   [$xml documentElement] appendChild $elem

} $xml asXML</lang>

<CharacterRemarks>
    <Character name="April">Bubbly: I'm &amp;gt; Tam and &amp;lt;= Emily</Character>
    <Character name="Tam O'Shanter">Burns: "When chapman billies leave the street ..."</Character>
    <Character name="Emily">Short &amp; shrift</Character>
</CharacterRemarks>

Using

Library: TclXML

<lang tcl>package require dom set xml [dom::DOMImplementation create] set root [dom::document createElement $xml CharacterRemarks] foreach {name comment} {

   April "Bubbly: I'm > Tam and <= Emily"
   "Tam O'Shanter" "Burns: \"When chapman billies leave the street ...\""
   Emily "Short & shrift"

} {

   set element [dom::document createElement $root Character]
   dom::element setAttribute $element name $name
   dom::document createTextNode $element $comment

} dom::DOMImplementation serialize $xml -indent 1</lang> produces (with line breaks added for clarity:

<?xml version="1.0"?>
<CharacterRemarks>
  <Character name="April">Bubbly: I'm &gt; Tam and &lt;= Emily</Character>
  <Character name="Tam O'Shanter">Burns: "When chapman billies leave the street ..."</Character>
  <Character name="Emily">Short &amp; shrift</Character>
</CharacterRemarks>

Vedit macro language

The input data is given in an edit buffer, one name+remark pair on each line line, separated with TAB character. <lang vedit> // Replace special characters with entities: Replace("&", "&", BEGIN+ALL+NOERR) // this must be the first replace! Replace("<", "<", BEGIN+ALL+NOERR) Replace(">", ">", BEGIN+ALL+NOERR) Replace("'", "'", BEGIN+ALL+NOERR) Replace('"', """, BEGIN+ALL+NOERR)

// Insert XML marking BOF IT("<CharacterRemarks>") IN Repeat(ALL) {

   Search("^.", REGEXP+ERRBREAK)
   IT('  <Character name="')
   Replace('|T', '">')
   EOL IT('</Character>')

} EOF IT("</CharacterRemarks>") IN </lang>

Example input:

April	Bubbly: I'm > Tam and <= Emily
Tam O'Shanter	Burns: "When chapman billies leave the street ..." 
Emily	Short & shrift

Produces this output:

<CharacterRemarks>
  <Character name="April">Bubbly: I&apos;m &gt; Tam and &lt;= Emily</Character>
  <Character name="Tam O&apos;Shanter">Burns: &quot;When chapman billies leave the street ...&quot; </Character>
  <Character name="Emily">Short &amp; shrift</Character>
</CharacterRemarks>

Visual Basic .NET

This example may be incorrect due to a recent change in the task requirements or a lack of testing. Please verify it and remove this message. If the example does not match the requirements or does not work, replace this message with Template:incorrect or fix the code yourself.

<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>