XML/Input
You are encouraged to solve this task according to the task description, using any language you may know.
Given the following XML fragment, extract the list of student names using whatever means desired. If the only viable method is to use XPath, refer the reader to the task XML and XPath.
<lang xml><Students>
<Student Name="April" Gender="F" DateOfBirth="1989-01-02" /> <Student Name="Bob" Gender="M" DateOfBirth="1990-03-04" /> <Student Name="Chad" Gender="M" DateOfBirth="1991-05-06" /> <Student Name="Dave" Gender="M" DateOfBirth="1992-07-08"> <Pet Type="dog" Name="Rover" /> </Student> <Student DateOfBirth="1993-09-10" Gender="F" Name="Émily" />
</Students></lang>
Expected Output
April Bob Chad Dave Émily
ActionScript
<lang actionscript>package {
import flash.display.Sprite;
public class XMLReading extends Sprite { public function XMLReading() { var xml:XML = <Students> <Student Name="April" /> <Student Name="Bob" /> <Student Name="Chad" /> <Student Name="Dave" /> <Student Name="Emily" /> </Students>; for each(var node:XML in xml..Student) { trace(node.@Name); } } }
}</lang>
Ada
Uses XML/Ada from AdaCore.
extract_students.adb: <lang Ada>with Sax.Readers; with Input_Sources.Strings; with Unicode.CES.Utf8; with My_Reader;
procedure Extract_Students is
Sample_String : String :=
"<Students>" &
"<Student Name=""April"" Gender=""F"" DateOfBirth=""1989-01-02"" />" & "<Student Name=""Bob"" Gender=""M"" DateOfBirth=""1990-03-04"" />" & "<Student Name=""Chad"" Gender=""M"" DateOfBirth=""1991-05-06"" />" & "<Student Name=""Dave"" Gender=""M"" DateOfBirth=""1992-07-08"">" & "<Pet Type=""dog"" Name=""Rover"" />" & "</Student>" & "<Student DateOfBirth=""1993-09-10"" Gender=""F"" Name=""Émily"" />" &
"</Students>";
Reader : My_Reader.Reader; Input : Input_Sources.Strings.String_Input;
begin
Input_Sources.Strings.Open (Sample_String, Unicode.CES.Utf8.Utf8_Encoding, Input); My_Reader.Parse (Reader, Input); Input_Sources.Strings.Close (Input);
end Extract_Students;</lang>
my_reader.ads: <lang Ada>with Sax.Attributes; with Sax.Readers; with Unicode.CES; package My_Reader is
type Reader is new Sax.Readers.Reader with null record; procedure Start_Element (Handler : in out Reader; Namespace_URI : Unicode.CES.Byte_Sequence := ""; Local_Name : Unicode.CES.Byte_Sequence := ""; Qname : Unicode.CES.Byte_Sequence := ""; Atts : Sax.Attributes.Attributes'Class);
end My_Reader;</lang>
my_reader.adb: <lang Ada>with Ada.Text_IO; package body My_Reader is
procedure Start_Element (Handler : in out Reader; Namespace_URI : Unicode.CES.Byte_Sequence := ""; Local_Name : Unicode.CES.Byte_Sequence := ""; Qname : Unicode.CES.Byte_Sequence := ""; Atts : Sax.Attributes.Attributes'Class) is begin if Local_Name = "Student" then Ada.Text_IO.Put_Line (Sax.Attributes.Get_Value (Atts, "Name")); end if; end Start_Element;
end My_Reader;</lang>
Output:
April Bob Chad Dave Émily
Alternative using a DOM document
<lang Ada>with Ada.Text_IO; with Sax.Readers; with Input_Sources.Strings; with Unicode.CES.Utf8; with DOM.Readers; with DOM.Core.Documents; with DOM.Core.Nodes; with DOM.Core.Attrs;
procedure Extract_Students is
Sample_String : String :=
"<Students>" &
"<Student Name=""April"" Gender=""F"" DateOfBirth=""1989-01-02"" />" & "<Student Name=""Bob"" Gender=""M"" DateOfBirth=""1990-03-04"" />" & "<Student Name=""Chad"" Gender=""M"" DateOfBirth=""1991-05-06"" />" & "<Student Name=""Dave"" Gender=""M"" DateOfBirth=""1992-07-08"">" & "<Pet Type=""dog"" Name=""Rover"" />" & "</Student>" & "<Student DateOfBirth=""1993-09-10"" Gender=""F"" Name=""Émily"" />" &
"</Students>";
Input : Input_Sources.Strings.String_Input; Reader : DOM.Readers.Tree_Reader; Document : DOM.Core.Document; List : DOM.Core.Node_List;
begin
Input_Sources.Strings.Open (Sample_String, Unicode.CES.Utf8.Utf8_Encoding, Input); DOM.Readers.Parse (Reader, Input); Input_Sources.Strings.Close (Input); Document := DOM.Readers.Get_Tree (Reader); List := DOM.Core.Documents.Get_Elements_By_Tag_Name (Document, "Student"); for I in 0 .. DOM.Core.Nodes.Length (List) - 1 loop Ada.Text_IO.Put_Line (DOM.Core.Attrs.Value (DOM.Core.Nodes.Get_Named_Item (DOM.Core.Nodes.Attributes (DOM.Core.Nodes.Item (List, I)), "Name") ) ); end loop; DOM.Readers.Free (Reader);
end Extract_Students;</lang>
output is the same.
Alternative version using Matreshka
Uses Matreshka's SAX API for XML.
main.adb:
<lang Ada>with League.Application; with XML.SAX.Input_Sources.Streams.Files; with XML.SAX.Simple_Readers;
with Handlers;
procedure Main is
Handler : aliased Handlers.Handler; Input : aliased XML.SAX.Input_Sources.Streams.Files.File_Input_Source; Reader : aliased XML.SAX.Simple_Readers.SAX_Simple_Reader;
begin
Input.Open_By_File_Name (League.Application.Arguments.Element (1)); Reader.Set_Content_Handler (Handler'Unchecked_Access); Reader.Parse (Input'Unchecked_Access);
end Main;</lang>
handlers.ads:
<lang Ada>with League.Strings; with XML.SAX.Attributes; with XML.SAX.Content_Handlers;
package Handlers is
type Handler is limited new XML.SAX.Content_Handlers.SAX_Content_Handler with null record;
overriding procedure Start_Element (Self : in out Handler; Namespace_URI : League.Strings.Universal_String; Local_Name : League.Strings.Universal_String; Qualified_Name : League.Strings.Universal_String; Attributes : XML.SAX.Attributes.SAX_Attributes; Success : in out Boolean);
overriding function Error_String (Self : Handler) return League.Strings.Universal_String;
end Handlers;</lang>
handlers.adb:
<lang Ada>with Ada.Wide_Wide_Text_IO;
package body Handlers is
use type League.Strings.Universal_String;
function "+" (Item : Wide_Wide_String) return League.Strings.Universal_String renames League.Strings.To_Universal_String;
------------------ -- Error_String -- ------------------
overriding function Error_String (Self : Handler) return League.Strings.Universal_String is begin return League.Strings.Empty_Universal_String; end Error_String;
------------------- -- Start_Element -- -------------------
overriding procedure Start_Element (Self : in out Handler; Namespace_URI : League.Strings.Universal_String; Local_Name : League.Strings.Universal_String; Qualified_Name : League.Strings.Universal_String; Attributes : XML.SAX.Attributes.SAX_Attributes; Success : in out Boolean) is begin if Qualified_Name = +"Student" then Ada.Wide_Wide_Text_IO.Put_Line (Attributes.Value (+"Name").To_Wide_Wide_String); end if; end Start_Element;
end Handlers;</lang>
Aikido
Put the XML in the file called t.xml <lang aikido> import xml
var s = openin ("t.xml") var tree = XML.parseStream (s)
foreach node tree {
if (node.name == "Students") { foreach studentnode node { if (studentnode.name == "Student") { println (studentnode.getAttribute ("Name")) } } }
}
</lang> The output is (Aikido doesn't support unicode rendering):
April Bob Chad Dave Émily
AutoHotkey
simply using regular expressions <lang AutoHotkey>students = ( <Students>
<Student Name="April" Gender="F" DateOfBirth="1989-01-02" /> <Student Name="Bob" Gender="M" DateOfBirth="1990-03-04" /> <Student Name="Chad" Gender="M" DateOfBirth="1991-05-06" /> <Student Name="Dave" Gender="M" DateOfBirth="1992-07-08"> <Pet Type="dog" Name="Rover" /> </Student> <Student DateOfBirth="1993-09-10" Gender="F" Name="Émily" />
</Students> )
quote = " ; " pos = 1 while, pos := RegExMatch(students, "Name=.(\w+)" . quote . "\sGender" , name, pos + 1) names .= name1 . "`n"
msgbox % names</lang>
AWK
The following code extracts the value of the property "Name" from every Student tag. It does not handle the &#CODE;; this can be left to others: a way to cope with it fastly, is to output a very simple HTML structure, so that the interpretation is left to an HTML reader/browser.
<lang awk>function parse_buf() {
if ( match(buffer, /<Student[ \t]+[^>]*Name[ \t]*=[ \t]*"([^"]*)"/, mt) != 0 ) { students[mt[1]] = 1 } buffer = ""
}
BEGIN {
FS="" mode = 0 buffer = "" li = 1
}
mode==1 {
for(i=1; i <= NF; i++) { buffer = buffer $i if ( $i == ">" ) { mode = 0; break; } } if ( mode == 0 ) { li = i } else { li = 1 } # let us process the buffer if "complete" if ( mode == 0 ) { parse_buf() }
}
mode==0 {
for(i=li; i <= NF; i++) { if ( $i == "<" ) { mode = 1 break; } } for(j=i; i <= NF; i++) { buffer = buffer $i if ( $i == ">" ) { mode = 0 parse_buf() } } li = 1
}
END {
for(k in students) { print k }
}</lang> Using getXML.awk written by Jan Weber, one could do this:
or
<lang awk>awk -f getXML.awk sample.xml | awk '
$1 == "TAG" {tag = $2} tag == "Student" && /Name=/ {print substr($0, index($0, "=") + 1)}
'</lang> Using xmlparser.awk by Steve Coile, one can do this:
<lang awk>gawk -f xmlparser.awk sample.xml | awk '
$1 == "begin" {tag = $2} $1 == "attrib" {attrib = $2} $1 == "value" && tag == "STUDENT" && attrib == "name" {print $2}
'</lang>
Both of these produce this output
April Bob Chad Dave Émily
Scripts in AWK are often one-liners. This one-liner implementation searches for Student tags and then displays the contents of their Name attribute. The following line is meant to be typed in on the command line of a Unix shell or an MS-DOS command window.
gawk -lxml 'XMLSTARTELEM == "Student" {print XMLATTR["Name"]}' rosetta.xml
Output:
April Bob Chad Dave Émily
BBC BASIC
<lang bbcbasic> INSTALL @lib$+"XMLLIB"
xmlfile$ = "C:\students.xml" PROC_initXML(xmlobj{}, xmlfile$) level% = FN_skipTo(xmlobj{}, "Students", 0) IF level%=0 ERROR 100, "Students not found" REPEAT IF FN_isTag(xmlobj{}) THEN tag$ = FN_nextToken(xmlobj{}) IF LEFT$(tag$, 8) = "<Student" THEN np% = INSTR(tag$, "Name") IF np% THEN PRINT FN_repEnt(EVAL(MID$(tag$, np%+5))) ENDIF ELSE dummy$ = FN_nextToken(xmlobj{}) ENDIF UNTIL FN_getLevel(xmlobj{}) < level% PROC_exitXML(xmlobj{})</lang>
Output:
April Bob Chad Dave Émily
C
<lang c>#include <stdio.h>
- include <stdlib.h>
- include <string.h>
- include <libxml/parser.h>
- include <libxml/tree.h>
static void print_names(xmlNode *node) {
xmlNode *cur_node = NULL; for (cur_node = node; cur_node; cur_node = cur_node->next) { if (cur_node->type == XML_ELEMENT_NODE) { if ( strcmp(cur_node->name, "Student") == 0 ) {
xmlAttr *prop = NULL; if ( (prop = xmlHasProp(cur_node, "Name")) != NULL ) { printf("%s\n", prop->children->content);
}
} } print_names(cur_node->children); }
}
const char *buffer =
"<Students>\n" " <Student Name=\"April\" Gender=\"F\" DateOfBirth=\"1989-01-02\" />\n" " <Student Name=\"Bob\" Gender=\"M\" DateOfBirth=\"1990-03-04\" />\n" " <Student Name=\"Chad\" Gender=\"M\" DateOfBirth=\"1991-05-06\" />\n" " <Student Name=\"Dave\" Gender=\"M\" DateOfBirth=\"1992-07-08\">\n" " <Pet Type=\"dog\" Name=\"Rover\" />\n" " </Student>\n" " <Student DateOfBirth=\"1993-09-10\" Gender=\"F\" Name=\"Émily\" />\n" "</Students>\n";
int main() {
xmlDoc *doc = NULL; xmlNode *root = NULL;
doc = xmlReadMemory(buffer, strlen(buffer), NULL, NULL, 0); if ( doc != NULL ) { root = xmlDocGetRootElement(doc); print_names(root); xmlFreeDoc(doc); } xmlCleanupParser(); return 0;
}</lang>
C++
<lang cpp>/* Using the Qt library's XML parser.
- /
- include <iostream>
- include <QDomDocument>
- include <QObject>
int main() {
QDomDocument doc;
doc.setContent( QObject::tr( "<Students>\n" "<Student Name=\"April\" Gender=\"F\" DateOfBirth=\"1989-01-02\" />\n" "<Student Name=\"Bob\" Gender=\"M\" DateOfBirth=\"1990-03-04\" />\n" "<Student Name=\"Chad\" Gender=\"M\" DateOfBirth=\"1991-05-06\" />\n" "<Student Name=\"Dave\" Gender=\"M\" DateOfBirth=\"1992-07-08\">\n" "<Pet Type=\"dog\" Name=\"Rover\" />\n" "</Student>\n" "<Student DateOfBirth=\"1993-09-10\" Gender=\"F\" Name=\"Émily\" />\n" "</Students>")); QDomElement n = doc.documentElement().firstChildElement("Student"); while(!n.isNull()) { std::cout << qPrintable(n.attribute("Name")) << std::endl; n = n.nextSiblingElement(); } return 0;
}</lang>
C#
<lang csharp> class Program {
static void Main(string[] args) { XDocument xmlDoc = XDocument.Load("XMLFile1.xml"); var query = from p in xmlDoc.Descendants("Student") select p.Attribute("Name");
foreach (var item in query) { Console.WriteLine(item.Value); } Console.ReadLine(); }
} </lang>
Clojure
This version uses the standard Clojure function xml-seq' <lang lisp> (import '(java.io ByteArrayInputStream)) (use 'clojure.xml) ; defines 'parse
(def xml-text "<Students>
<Student Name='April' Gender='F' DateOfBirth='1989-01-02' /> <Student Name='Bob' Gender='M' DateOfBirth='1990-03-04' /> <Student Name='Chad' Gender='M' DateOfBirth='1991-05-06' /> <Student Name='Dave' Gender='M' DateOfBirth='1992-07-08'> <Pet Type='dog' Name='Rover' /> </Student> <Student DateOfBirth='1993-09-10' Gender='F' Name='Émily' />
</Students>")
(def students (parse (-> xml-text .getBytes ByteArrayInputStream.))) </lang>
The parse produces a data structure where each element is represented as a map with :tag, :attrs, and :content keys. Thus the "April" element becomes {:tag :Student, :attrs {:Name "April", :Gender "F", :DateOfBirth "1989-01-02"}, :content nil}. xml-seq produces a sequence of such nodes by walking the resulting tree.
<lang lisp> (doseq [{:keys [tag attrs]} (xml-seq students)]
(if (= :Student tag) (println (:Name attrs))))
</lang>
Common Lisp
<lang lisp>(defparameter *xml-blob* "<Students>
<Student Name=\"April\" Gender=\"F\" DateOfBirth=\"1989-01-02\" /> <Student Name=\"Bob\" Gender=\"M\" DateOfBirth=\"1990-03-04\" /> <Student Name=\"Chad\" Gender=\"M\" DateOfBirth=\"1991-05-06\" /> <Student Name=\"Dave\" Gender=\"M\" DateOfBirth=\"1992-07-08\"> <Pet Type=\"dog\" Name=\"Rover\" /> </Student> <Student DateOfBirth=\"1993-09-10\" Gender=\"F\" Name=\"Émily\" />
</Students>")
(let* ((document (cxml:parse *xml-blob* (cxml-dom:make-dom-builder)))
(students (dom:item (dom:get-elements-by-tag-name document "Students") 0)) (student-names '())) (dom:do-node-list (child (dom:child-nodes students) (nreverse student-names)) (when (dom:element-p child) (push (dom:get-attribute child "Name") student-names))))</lang>
produces<lang lisp>("April" "Bob" "Chad" "Dave" "Émily")</lang>
D
<lang d>import kxml.xml; char[]xmlinput = "<Students>
<Student Name=\"April\" Gender=\"F\" DateOfBirth=\"1989-01-02\" /> <Student Name=\"Bob\" Gender=\"M\" DateOfBirth=\"1990-03-04\" /> <Student Name=\"Chad\" Gender=\"M\" DateOfBirth=\"1991-05-06\" /> <Student Name=\"Dave\" Gender=\"M\" DateOfBirth=\"1992-07-08\"> <Pet Type=\"dog\" Name=\"Rover\" /> </Student> <Student DateOfBirth=\"1993-09-10\" Gender=\"F\" Name=\"Émily\" />
</Students>";
void main() {
auto root = readDocument(xmlinput); foreach(students;root.getChildren) if (!students.isCData && students.getName == "Students") { // now look for student subnodes foreach(student;students.getChildren) if (!student.isCData && student.getName == "Student") { // we found a student! std.stdio.writefln("%s",student.getAttribute("Name")); } // we only want one, so break out of the loop once we find a match break; }
}</lang>
Delphi
<lang Delphi> //You need to use these units uses
SysUtils, Dialogs, XMLIntf, XMLDoc;
//..............................................
//This function process the XML function GetStudents(aXMLInput: string): string; var
XMLDoc: IXMLDocument; i: Integer;
begin
//Creating the TXMLDocument instance XMLDoc:= TXMLDocument.Create(nil);
//Loading the XML string XMLDoc.LoadFromXML(aXMLInput);
//Parsing the xml document for i:=0 to XMLDoc.DocumentElement.ChildNodes.Count - 1 do Result:= Result + XMLDoc.DocumentElement.ChildNodes.Get(i).GetAttributeNS('Name', ) + #13#10;
//Removing the trailing #13#10 characters Result:= Trim(Result);
end;
//..............................................
//Consuming code example (fragment) var
XMLInput: string;
begin
XMLInput:= '<Students>' + '<Student Name="April" Gender="F" DateOfBirth="1989-01-02" />' + '<Student Name="Bob" Gender="M" DateOfBirth="1990-03-04" />' + '<Student Name="Chad" Gender="M" DateOfBirth="1991-05-06" />' + '<Student Name="Dave" Gender="M" DateOfBirth="1992-07-08">' + '<Pet Type="dog" Name="Rover" />' + '</Student>' + '<Student DateOfBirth="1993-09-10" Gender="F" Name="Émily" />'+ '</Students>'; Showmessage(GetStudents(XMLInput));
end; </lang>
Factor
<lang factor>USING: io sequences xml xml.data xml.traversal ;
- print-student-names ( string -- )
string>xml "Student" tags-named [ "Name" attr print ] each ;
"""<Students>
<Student Name="April" Gender="F" DateOfBirth="1989-01-02" /> <Student Name="Bob" Gender="M" DateOfBirth="1990-03-04" /> <Student Name="Chad" Gender="M" DateOfBirth="1991-05-06" /> <Student Name="Dave" Gender="M" DateOfBirth="1992-07-08"> <Pet Type="dog" Name="Rover" /> </Student> <Student DateOfBirth="1993-09-10" Gender="F" Name="Émily" />
</Students>""" print-student-names</lang>
Fantom
<lang fantom> using xml
class XmlInput {
public static Void main () { // create the XML parser parser := XParser(File("sample-xml.xml".toUri).in) // parse the document, creating an XML document XDoc doc := parser.parseDoc // walk through each child element from the root of the document doc.root.elems.each |elem| { // printing the Name attribute of all Students if (elem.name == "Student") { echo (elem.get("Name")) } } }
} </lang>
Forth
<lang forth>include ffl/est.fs include ffl/str.fs include ffl/xis.fs
\ Build input string str-create xmlstr
- x+ xmlstr str-append-string ;
s\" <Students>\n" x+ s\" <Student Name=\"April\" Gender=\"F\" DateOfBirth=\"1989-01-02\" />\n" x+ s\" <Student Name=\"Bob\" Gender=\"M\" DateOfBirth=\"1990-03-04\" />\n" x+ s\" <Student Name=\"Chad\" Gender=\"M\" DateOfBirth=\"1991-05-06\" />\n" x+ s\" <Student Name=\"Dave\" Gender=\"M\" DateOfBirth=\"1992-07-08\">\n" x+ s\" <Pet Type=\"dog\" Name=\"Rover\" />\n" x+ s\" </Student>\n" x+ s\" <Student DateOfBirth=\"1993-09-10\" Gender=\"F\" Name=\"Émily\" />\n" x+ s\" </Students>\n" x+
\ Setup xml parser xis-create xmlparser xmlstr str-get xmlparser xis-set-string
\ Parse the xml
- xmlparse
BEGIN xmlparser xis-read dup xis.error <> over xis.done <> AND WHILE dup xis.start-tag = over xis.empty-element = OR IF drop s" Student" compare 0= IF 0 ?DO 2swap s" Name" compare 0= IF type cr ELSE 2drop THEN LOOP ELSE xis+remove-attribute-parameters THEN ELSE xis+remove-read-parameters THEN REPEAT drop
xmlparse</lang>
Go
Go's xml.Unmarshal uses reflection to fill in data-structures recursively. <lang go>package main
import (
"encoding/xml" "fmt"
)
const XML_DATA = ` <Students>
<Student Name="April" Gender="F" DateOfBirth="1989-01-02" /> <Student Name="Bob" Gender="M" DateOfBirth="1990-03-04" /> <Student Name="Chad" Gender="M" DateOfBirth="1991-05-06" /> <Student Name="Dave" Gender="M" DateOfBirth="1992-07-08"> <Pet Type="dog" Name="Rover" /> </Student> <Student DateOfBirth="1993-09-10" Gender="F" Name="Émily" />
</Students> `
type Students struct {
Student []Student
}
type Student struct {
Name string `xml:",attr"` // Gender string `xml:",attr"` // DateOfBirth string `xml:",attr"` // Pets []Pet `xml:"Pet"`
}
type Pet struct {
Type string `xml:",attr"` Name string `xml:",attr"`
}
// xml.Unmarshal quietly skips well formed input with no corresponding // member in the output data structure. With Gender, DateOfBirth, and // Pets commented out of the Student struct, as above, Student contains // only Name, and this is the only value extracted from the input XML_DATA. func main() {
data := new(Students) err := xml.Unmarshal([]byte(XML_DATA), data) if err != nil { fmt.Println(err) return } for _, s := range data.Student { fmt.Println(s.Name) }
}</lang>
- Output:
April Bob Chad Dave Émily
Groovy
<lang groovy>def input = """<Students>
<Student Name="April" Gender="F" DateOfBirth="1989-01-02" /> <Student Name="Bob" Gender="M" DateOfBirth="1990-03-04" /> <Student Name="Chad" Gender="M" DateOfBirth="1991-05-06" /> <Student Name="Dave" Gender="M" DateOfBirth="1992-07-08"> <Pet Type="dog" Name="Rover" /> </Student> <Student DateOfBirth="1993-09-10" Gender="F" Name="Émily" />
</Students>"""
def students = new XmlParser().parseText(input) students.each { println it.'@Name' }</lang>
Haskell
<lang haskell>import Data.Maybe import Text.XML.Light
students="<Students>"++
" <Student Name=\"April\" Gender=\"F\" DateOfBirth=\"1989-01-02\" />"++ " <Student Name=\"Bob\" Gender=\"M\" DateOfBirth=\"1990-03-04\" />"++ " <Student Name=\"Chad\" Gender=\"M\" DateOfBirth=\"1991-05-06\"/>"++ " <Student Name=\"Dave\" Gender=\"M\" DateOfBirth=\"1992-07-08\">"++ " <Pet Type=\"dog\" Name=\"Rover\" /> </Student>"++ " <Student DateOfBirth=\"1993-09-10\" Gender=\"F\" Name=\"Émily\" />"++ "</Students>"
xmlRead elm name = mapM_ putStrLn
. concatMap (map (fromJust.findAttr (unqual name)).filterElementsName (== unqual elm)) . onlyElems. parseXML</lang>
Show names: <lang haskell>*Main> xmlRead "Student" "Name" students April Bob Chad Dave Émily</lang>
HicEst
<lang HicEst>CHARACTER in*1000, out*100
READ(ClipBoard) in EDIT(Text=in, SPR='"', Right='<Student', Right='Name=', Word=1, WordEnd, APpendTo=out, DO)</lang>
out is returned as: April Bob Chad Dave Émily
J
J's system includes several XML processing libraries. This task is probably best addressed using XPath (this is the type of problem XPath was designed to solve), but the task description implicitly discourages that method. So we can use the SAX library instead:
<lang j>load'xml/sax'
saxclass 'Students' startElement =: ([: smoutput 'Name' getAttribute~ [)^:('Student'-:]) cocurrent'base'
process_Students_ XML</lang>
April Bob Chad Dave Émily
and the definition of the variable XML
:
<lang j>XML=: noun define
<Students>
<Student Name="April" Gender="F" DateOfBirth="1989-01-02" /> <Student Name="Bob" Gender="M" DateOfBirth="1990-03-04" /> <Student Name="Chad" Gender="M" DateOfBirth="1991-05-06" /> <Student Name="Dave" Gender="M" DateOfBirth="1992-07-08"> <Pet Type="dog" Name="Rover" /> </Student> <Student DateOfBirth="1993-09-10" Gender="F" Name="Émily" />
</Students> )</lang>
Java
<lang java>import java.io.IOException; import java.io.StringReader; import org.xml.sax.Attributes; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.XMLReader; import org.xml.sax.helpers.DefaultHandler; import org.xml.sax.helpers.XMLReaderFactory;
public class StudentHandler extends DefaultHandler {
public static void main(String[] args)throws Exception{ String xml = "<Students>\n"+ "<Student Name=\"April\" Gender=\"F\" DateOfBirth=\"1989-01-02\" />\n"+ "<Student Name=\"Bob\" Gender=\"M\" DateOfBirth=\"1990-03-04\" />\n"+ "<Student Name=\"Chad\" Gender=\"M\" DateOfBirth=\"1991-05-06\" />\n"+ "<Student Name=\"Dave\" Gender=\"M\" DateOfBirth=\"1992-07-08\">\n"+ " <Pet Type=\"dog\" Name=\"Rover\" />\n"+ "</Student>\n"+ "<Student DateOfBirth=\"1993-09-10\" Gender=\"F\" Name=\"Émily\" />\n"+ "</Students>"; StudentHandler handler = new StudentHandler(); handler.parse(new InputSource(new StringReader(xml))); }
public void parse(InputSource src) throws SAXException, IOException {
XMLReader parser = XMLReaderFactory.createXMLReader();
parser.setContentHandler(this); parser.parse(src); }
@Override public void characters(char[] ch, int start, int length) throws SAXException { //if there were text as part of the elements, we would deal with it here //by adding it to a StringBuffer, but we don't have to for this task super.characters(ch, start, length); }
@Override public void endElement(String uri, String localName, String qName) throws SAXException { //this is where we would get the info from the StringBuffer if we had to, //but all we need is attributes super.endElement(uri, localName, qName); }
@Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { if(qName.equals("Student")){ System.out.println(attributes.getValue("Name")); } }
}</lang>
JavaScript
This version tested against Chrome 5, Firefox 3.6, and IE 8: <lang JavaScript> var xmlstr = '<Students>' +
'<Student Name="April" Gender="F" DateOfBirth="1989-01-02" />' + '<Student Name="Bob" Gender="M" DateOfBirth="1990-03-04" />' + '<Student Name="Chad" Gender="M" DateOfBirth="1991-05-06" />' + '<Student Name="Dave" Gender="M" DateOfBirth="1992-07-08">' + '<Pet Type="dog" Name="Rover" />' + '</Student>' + '<Student DateOfBirth="1993-09-10" Gender="F" Name="Émily" />' +
'</Students>';
var list = xmlstr.match(/<Student .*? \/>/g); var output = ; for (var i = 0; i < list.length; i++) {
if (i > 0) { output += ', '; } var tmp = list[i].match(/Name="(.*?)"/); output += tmp[1];
}
// Bounce it through a HTML element to handle Unicode for us var l = document.createElement('p'); l.innerHTML = output; alert(l.innerHTML); </lang>
Alternatively, use the E4X featureset (currently only in Firefox): <lang JavaScript> var xmlstr = '<Students>' +
'<Student Name="April" Gender="F" DateOfBirth="1989-01-02" />' + '<Student Name="Bob" Gender="M" DateOfBirth="1990-03-04" />' + '<Student Name="Chad" Gender="M" DateOfBirth="1991-05-06" />' + '<Student Name="Dave" Gender="M" DateOfBirth="1992-07-08">' + '<Pet Type="dog" Name="Rover" />' + '</Student>' + '<Student DateOfBirth="1993-09-10" Gender="F" Name="Émily" />' +
'</Students>'; var xml = XML(xmlstr); var list = xml.Student.@Name; var output = ; for (var i = 0; i < list.length(); i++) {
if (i > 0) { output += ', '; } output += list[i];
}
alert(output); </lang>
Lua
Requires LuaExpat <lang lua> require 'lxp' data = [[<Students>
<Student Name="April" Gender="F" DateOfBirth="1989-01-02" /> <Student Name="Bob" Gender="M" DateOfBirth="1990-03-04" /> <Student Name="Chad" Gender="M" DateOfBirth="1991-05-06" /> <Student Name="Dave" Gender="M" DateOfBirth="1992-07-08"> <Pet Type="dog" Name="Rover" /> </Student> <Student DateOfBirth="1993-09-10" Gender="F" Name="Émily" />
</Students>]]
p = lxp.new({StartElement = function (parser, name, attr) if name == 'Student' and attr.Name then print(attr.Name) end end})
p:parse(data) p:close() </lang> Output:
April Bob Chad Dave Émily
Mathematica
<lang Mathematica>Column[Cases[Import["test.xml","XML"],Rule["Name", n_ ] -> n,Infinity]]</lang> Output:
April Bob Chad Dave Émily
newLISP
<lang newlisp> (set 'xml-input "<Students>
<Student Name=\"April\" Gender=\"F\" DateOfBirth=\"1989-01-02\" /> <Student Name=\"Bob\" Gender=\"M\" DateOfBirth=\"1990-03-04\" /> <Student Name=\"Chad\" Gender=\"M\" DateOfBirth=\"1991-05-06\" /> <Student Name=\"Dave\" Gender=\"M\" DateOfBirth=\"1992-07-08\"> <Pet Type=\"dog\" Name=\"Rover\" /> </Student> <Student DateOfBirth=\"1993-09-10\" Gender=\"F\" Name=\"Émily\" />
</Students>")
(set 'sexp (xml-parse xml-input))
(dolist (x (ref-all "Name" sexp)) (if (= (length x) 6) (println (last (sexp (chop x)))))) </lang>
Output:
April Bob Chad Dave Émily
Objeck
<lang objeck> use XML;
bundle Default {
class Test { function : Main(args : String[]) ~ Nil { in := String->New(); in->Append("<Students>"); in->Append("<Student Name=\"April\" Gender=\"F\" DateOfBirth=\"1989-01-02\" />"); in->Append("<Student Name=\"Bob\" Gender=\"M\" DateOfBirth=\"1990-03-04\" />"); in->Append("<Student Name=\"Chad\" Gender=\"M\" DateOfBirth=\"1991-05-06\" />"); in->Append("<Student Name=\"Dave\" Gender=\"M\" DateOfBirth=\"1992-07-08\">"); in->Append("<Pet Type=\"dog\" Name=\"Rover\" />"); in->Append("</Student>"); in->Append("<Student DateOfBirth=\"1993-09-10\" Gender=\"F\" Name=\"Émily\" /></Students>"); parser := XmlParser->New(in); if(parser->Parse()) { root := parser->GetRoot(); children := root->GetChildren("Student"); each(i : children) { child : XMLElement := children->Get(i)->As(XMLElement); XMLElement->DecodeString(child->GetAttribute("Name"))->PrintLine(); }; }; } }
} </lang>
OCaml
from the toplevel using the library xml-light: <lang ocaml># #directory "+xml-light" (* or maybe "+site-lib/xml-light" *) ;;
- #load "xml-light.cma" ;;
- let x = Xml.parse_string "
<Students> <Student Name='April' Gender='F' DateOfBirth='1989-01-02' /> <Student Name='Bob' Gender='M' DateOfBirth='1990-03-04' /> <Student Name='Chad' Gender='M' DateOfBirth='1991-05-06' /> <Student Name='Dave' Gender='M' DateOfBirth='1992-07-08'> <Pet Type='dog' Name='Rover' /> </Student> <Student DateOfBirth='1993-09-10' Gender='F' Name='Émily' /> </Students>" in Xml.iter (function Xml.Element ("Student", attrs, _) -> List.iter (function ("Name", name) -> print_endline name | _ -> ()) attrs | _ -> ()) x ;;
April Bob Chad Dave Émily - : unit = ()</lang>
Another solution using the library xmlm: <lang ocaml>#directory "+xmlm"
- load "xmlm.cmo"
open Xmlm
let str = "
<Students> <Student Name='April' Gender='F' DateOfBirth='1989-01-02' /> <Student Name='Bob' Gender='M' DateOfBirth='1990-03-04' /> <Student Name='Chad' Gender='M' DateOfBirth='1991-05-06' /> <Student Name='Dave' Gender='M' DateOfBirth='1992-07-08'> <Pet Type='dog' Name='Rover' /> </Student> <Student DateOfBirth='1993-09-10' Gender='F' Name='Émily' /> </Students>"
let xi = make_input(`String(0, str))
let () =
while not(eoi xi) do match Xmlm.input xi with | `El_start ((_, "Student"), attrs) -> List.iter (function ((_, "Name"), name) -> print_endline name | _ -> ()) attrs | _ -> () done</lang>
using the ocaml expat wrapper:
<lang ocaml>open Expat
let xml_str = "
<Students> <Student Name='April' Gender='F' DateOfBirth='1989-01-02' /> <Student Name='Bob' Gender='M' DateOfBirth='1990-03-04' /> <Student Name='Chad' Gender='M' DateOfBirth='1991-05-06' /> <Student Name='Dave' Gender='M' DateOfBirth='1992-07-08'> <Pet Type='dog' Name='Rover' /> </Student> <Student DateOfBirth='1993-09-10' Gender='F' Name='Émily' /> </Students>"
let () =
let p = parser_create None in set_start_element_handler p (fun tag attrs -> if tag = "Student" then List.iter (function ("Name", name) -> print_endline name | _ -> ()) attrs ); parse p xml_str; final p;</lang>
OpenEdge/Progress
The following example uses the X-DOCUMENT DOM parser. For larger documents the SAX parser is recommended.
<lang progress> DEF VAR lcc AS LONGCHAR. DEF VAR hxdoc AS HANDLE. DEF VAR hxstudents AS HANDLE. DEF VAR hxstudent AS HANDLE. DEF VAR hxname AS HANDLE. DEF VAR ii AS INTEGER EXTENT 2. DEF VAR cstudents AS CHARACTER.
lcc = '<Students>'
+ '<Student Name="April" Gender="F" DateOfBirth="1989-01-02" />' + '<Student Name="Bob" Gender="M" DateOfBirth="1990-03-04" />' + '<Student Name="Chad" Gender="M" DateOfBirth="1991-05-06" />' + '<Student Name="Dave" Gender="M" DateOfBirth="1992-07-08">' + '<Pet Type="dog" Name="Rover" />' + '</Student>' + '<Student DateOfBirth="1993-09-10" Gender="F" Name="Émily" />' + '</Students>'.
CREATE X-DOCUMENT hxdoc. hxdoc:LOAD( 'LONGCHAR', lcc, FALSE ).
DO ii[1] = 1 TO hxdoc:NUM-CHILDREN:
CREATE X-NODEREF hxstudents. hxdoc:GET-CHILD( hxstudents, ii[1] ). IF hxstudents:NAME = 'Students' THEN DO ii[2] = 1 TO hxstudents:NUM-CHILDREN: CREATE X-NODEREF hxstudent. hxstudents:GET-CHILD( hxstudent, ii[2] ). IF hxstudent:NAME = 'Student' THEN cstudents = cstudents + hxstudent:GET-ATTRIBUTE( 'Name' ) + '~n'. DELETE OBJECT hxstudent. END. DELETE OBJECT hxstudents.
END. DELETE OBJECT hxdoc.
MESSAGE cstudents VIEW-AS ALERT-BOX.</lang>
Output:
--------------------------- Message --------------------------- April Bob Chad Dave Émily --------------------------- OK ---------------------------
Oz
<lang oz>declare
[XMLParser] = {Module.link ['x-oz://system/xml/Parser.ozf']} Parser = {New XMLParser.parser init}
Data = "<Students>" #" <Student Name=\"April\" Gender=\"F\" DateOfBirth=\"1989-01-02\" />" #" <Student Name=\"Bob\" Gender=\"M\" DateOfBirth=\"1990-03-04\" />" #" <Student Name=\"Chad\" Gender=\"M\" DateOfBirth=\"1991-05-06\" />" #" <Student Name=\"Dave\" Gender=\"M\" DateOfBirth=\"1992-07-08\">" #" <Pet Type=\"dog\" Name=\"Rover\" />" #" </Student>" #" <Student DateOfBirth=\"1993-09-10\" Gender=\"F\" Name=\"Émily\" />" #"</Students>"
fun {IsStudentElement X} case X of element(name:'Student' ...) then true else false end end
fun {GetStudentName element(attributes:As ...)} [NameAttr] = {Filter As fun {$ attribute(name:N ...)} N == 'Name' end} in NameAttr.value end
[StudentsDoc] = {Parser parseVS(Data $)} Students = {Filter StudentsDoc.children IsStudentElement} StudentNames = {Map Students GetStudentName}
in
{ForAll StudentNames System.showInfo}</lang>
Perl
<lang perl>use XML::Simple;
my $ref = XMLin('<Students>
<Student Name="April" Gender="F" DateOfBirth="1989-01-02" /> <Student Name="Bob" Gender="M" DateOfBirth="1990-03-04" /> <Student Name="Chad" Gender="M" DateOfBirth="1991-05-06" /> <Student Name="Dave" Gender="M" DateOfBirth="1992-07-08"> <Pet Type="dog" Name="Rover" /> </Student> <Student DateOfBirth="1993-09-10" Gender="F" Name="Émily" />
</Students>');
print join( "\n", map { $_->{'Name'} } @{$ref->{'Student'}});</lang>
PHP
<lang PHP><?php $data = '<Students>
<Student Name="April" Gender="F" DateOfBirth="1989-01-02" /> <Student Name="Bob" Gender="M" DateOfBirth="1990-03-04" /> <Student Name="Chad" Gender="M" DateOfBirth="1991-05-06" /> <Student Name="Dave" Gender="M" DateOfBirth="1992-07-08"> <Pet Type="dog" Name="Rover" /> </Student> <Student DateOfBirth="1993-09-10" Gender="F" Name="Émily" />
</Students>'; $xml = new XMLReader(); $xml->xml( $data ); while ( $xml->read() ) if ( XMLREADER::ELEMENT == $xml->nodeType && $xml->localName == 'Student' ) echo $xml->getAttribute('Name') . "\n"; ?></lang>
PicoLisp
<lang PicoLisp>(load "@lib/xm.l")
(mapcar
'((L) (attr L 'Name)) (body (in "file.xml" (xml))) )</lang>
Output:
-> ("April" "Bob" "Chad" "Dave" "Émily")
Pike
<lang Pike> string in = "<Students>\n"
" <Student Name=\"April\" Gender=\"F\" DateOfBirth=\"1989-01-02\" />\n" " <Student Name=\"Bob\" Gender=\"M\" DateOfBirth=\"1990-03-04\" />\n" " <Student Name=\"Chad\" Gender=\"M\" DateOfBirth=\"1991-05-06\" />\n" " <Student Name=\"Dave\" Gender=\"M\" DateOfBirth=\"1992-07-08\">\n" " <Pet Type=\"dog\" Name=\"Rover\" />\n" " </Student>\n" " <Student DateOfBirth=\"1993-09-10\" Gender=\"F\" Name=\"Émily\" />\n" "</Students>\n";
object s = Parser.XML.Tree.simple_parse_input(in);
array collect = ({}); s->walk_inorder(lambda(object node)
{ if (node->get_tag_name() == "Student") collect += ({ node->get_attributes()->Name }); });
write("%{%s\n%}", collect);</lang>
Output:
April Bob Chad Dave Émily
PowerShell
<lang Powershell> [xml]$xml = @' <Students>
<Student Name="April" Gender="F" DateOfBirth="1989-01-02" /> <Student Name="Bob" Gender="M" DateOfBirth="1990-03-04" /> <Student Name="Chad" Gender="M" DateOfBirth="1991-05-06" /> <Student Name="Dave" Gender="M" DateOfBirth="1992-07-08"> <Pet Type="dog" Name="Rover" /> </Student> <Student DateOfBirth="1993-09-10" Gender="F" Name="Émily" />
</Students> '@
foreach ($node in $xml.DocumentElement.ChildNodes) {$node.Name}
</lang>
OpenEdge ABL/Progress 4GL
<lang OpenEdgeABL> /** ==== Definitions ===== **/ DEFINE VARIABLE chXMLString AS LONGCHAR NO-UNDO. DEFINE TEMP-TABLE ttStudent NO-UNDO XML-NODE-NAME 'Student'
FIELD StudentName AS CHARACTER XML-NODE-TYPE 'attribute' XML-NODE-NAME 'Name' LABEL 'Name' FIELD Gender AS CHARACTER XML-NODE-TYPE 'attribute' XML-NODE-NAME 'Gender' LABEL 'Gender' FIELD DateOfBirth AS CHARACTER XML-NODE-TYPE 'attribute' XML-NODE-NAME 'DateOfBirth' LABEL 'Date Of Birth'.
DEFINE DATASET dsStudents XML-NODE-NAME 'Students' FOR ttStudent.
/** ==== Main block ====**/
/** ASSIGN the XML string with the XML data.. **/ chXMLString = '<Students>~
<Student Name="April" Gender="F" DateOfBirth="1989-01-02" />~ <Student Name="Bob" Gender="M" DateOfBirth="1990-03-04" />~ <Student Name="Chad" Gender="M" DateOfBirth="1991-05-06" />~ <Student Name="Dave" Gender="M" DateOfBirth="1992-07-08">~ <Pet Type="dog" Name="Rover" />~ </Student>~ <Student DateOfBirth="1993-09-10" Gender="F" Name="Émily" />~ </Students>'.
/** Read the string into the dataset...**/ DATASET dsStudents:READ-XML('LONGCHAR', chXMLString, 'EMPTY',?,?).
/** Loop thought each temp-table record to produce the results...**/ FOR EACH ttStudent:
DISPLAY ttStudent.StudentName.
END.
</lang>
PureBasic
Uses a PureBasic XML library (which is linked automatically) that is based on the library expat XML parser licensed under the MIT license. <lang PureBasic>Define studentNames.String, src$
src$ = "<Students>" src$ + "<Student Name='April' Gender='F' DateOfBirth='1989-01-02' />" src$ + "<Student Name='Bob' Gender='M' DateOfBirth='1990-03-04' />" src$ + "<Student Name='Chad' Gender='M' DateOfBirth='1991-05-06' />" src$ + "<Student Name='Dave' Gender='M' DateOfBirth='1992-07-08'>" src$ + "<Pet Type='dog' Name='Rover' />" src$ + "</Student>" src$ + "<Student DateOfBirth='1993-09-10' Gender='F' Name='Émily' />" src$ + "</Students>"
- This procedure is generalized to match any attribute of any normal element's node name
- i.e. get_values(MainXMLNode(0),"Pet","Type",@petName.String) and displaying petName\s
- would display "dog".
Procedure get_values(*cur_node, nodeName$, attribute$, *valueResults.String)
;If nodeName$ and attribute$ are matched then the value ;will be added to the string structure pointed to by *valueResults . Protected result$
While *cur_node If XMLNodeType(*cur_node) = #PB_XML_Normal result$ = GetXMLNodeName(*cur_node) If result$ = nodeName$ If ExamineXMLAttributes(*cur_node) While NextXMLAttribute(*cur_node) If XMLAttributeName(*cur_node) = attribute$ If *valueResults <> #Null *valueResults\s + XMLAttributeValue(*cur_node) + Chr(13) ;value + carriage-return EndIf EndIf Wend EndIf EndIf EndIf get_values(ChildXMLNode(*cur_node), nodeName$, attribute$, *valueResults) *cur_node = NextXMLNode(*cur_node) Wend
EndProcedure
CatchXML(0,@src$,Len(src$))
If IsXML(0)
get_values(MainXMLNode(0), "Student", "Name",@studentNames) MessageRequester("Student Names", studentNames\s) FreeXML(0)
EndIf </lang> Sample output:
April Bob Chad Dave Émily
Python
<lang python>import xml.dom.minidom
doc = """<Students>
<Student Name="April" Gender="F" DateOfBirth="1989-01-02" /> <Student Name="Bob" Gender="M" DateOfBirth="1990-03-04" /> <Student Name="Chad" Gender="M" DateOfBirth="1991-05-06" /> <Student Name="Dave" Gender="M" DateOfBirth="1992-07-08"> <Pet Type="dog" Name="Rover" /> </Student> <Student DateOfBirth="1993-09-10" Gender="F" Name="Émily" />
</Students>"""
doc = xml.dom.minidom.parseString(doc)
for i in doc.getElementsByTagName("Student"):
print i.getAttribute("Name")</lang>
R
<lang R>library(XML)
- Read in XML string
str <- readLines(tc <- textConnection('<Students>
<Student Name="April" Gender="F" DateOfBirth="1989-01-02" /> <Student Name="Bob" Gender="M" DateOfBirth="1990-03-04" /> <Student Name="Chad" Gender="M" DateOfBirth="1991-05-06" /> <Student Name="Dave" Gender="M" DateOfBirth="1992-07-08"> <Pet Type="dog" Name="Rover" /> </Student> <Student DateOfBirth="1993-09-10" Gender="F" Name="Émily" />
</Students>')) close(tc) str</lang>
[1] "<Students>" [2] " <Student Name=\"April\" Gender=\"F\" DateOfBirth=\"1989-01-02\" />" [3] " <Student Name=\"Bob\" Gender=\"M\" DateOfBirth=\"1990-03-04\" />" [4] " <Student Name=\"Chad\" Gender=\"M\" DateOfBirth=\"1991-05-06\" />" [5] " <Student Name=\"Dave\" Gender=\"M\" DateOfBirth=\"1992-07-08\">" [6] " <Pet Type=\"dog\" Name=\"Rover\" />" [7] " </Student>" [8] " <Student DateOfBirth=\"1993-09-10\" Gender=\"F\" Name=\"Émily\" />" [9] "</Students>"
<lang R>#Convert to an XML tree xmltree <- xmlTreeParse(str)
- Retrieve the students, and how many there are
students <- xmltree$doc$children$Students nstudents <- length(students)
- Get each of their names
studentsnames <- character(nstudents) for(i in 1:nstudents) {
this.student <- students$children[i]$Student studentsnames[i] <- this.student$attributes["Name"]
}
- Change the encoding so that Emily displays correctly
Encoding(studentsnames) <- "UTF-8" studentsnames</lang>
[1] "April" "Bob" "Chad" "Dave" "Émily"
Rascal
<lang rascal>import lang::xml::DOM;
public void getNames(loc a){ D = parseXMLDOM(readFile(a)); visit(D){ case element(_,"Student",[_*,attribute(_,"Name", x),_*]): println(x); }; }</lang> Output: <lang rascal>rascal>getNames(|file:///Users/.../Desktop/xmlinput.xml|) April Bob Chad Dave Émily ok</lang>
REBOL
<lang REBOL>REBOL [ Title: "XML Reading" Author: oofoe Date: 2009-12-08 URL: http://rosettacode.org/wiki/XML_Reading ]
xml: { <Students>
<Student Name="April" Gender="F" DateOfBirth="1989-01-02" /> <Student Name="Bob" Gender="M" DateOfBirth="1990-03-04" /> <Student Name="Chad" Gender="M" DateOfBirth="1991-05-06" /> <Student Name="Dave" Gender="M" DateOfBirth="1992-07-08"> <Pet Type="dog" Name="Rover" /> </Student> <Student DateOfBirth="1993-09-10" Gender="F" Name="Émily" />
</Students> }
- REBOL has a simple built-in XML parser. It's not terribly fancy, but
- it's easy to use. It converts the XML into a nested list of blocks
- which can be accessed using standard REBOL path operators. The only
- annoying part (in this case) is that it does try to preserve
- whitespace, so some of the parsed elements are just things like line
- endings and whatnot, which I need to ignore.
- Once I have drilled down to the individual student records, I can
- just use the standard REBOL 'select' to locate the requested
- property.
data: parse-xml xml students: data/3/1/3 ; Drill down to student records. foreach student students [ if block! = type? student [ ; Ignore whitespace elements. print select student/2 "Name" ] ]</lang>
Output:
April Bob Chad Dave Émily
REXX
version 1
<lang rexx>/*REXX program to extract student names from an XML string(s). */ g.= g.1='<Students> ' g.2=' <Student Name="April" Gender="F" DateOfBirth="1989-01-02" /> ' g.3=' <Student Name="Bob" Gender="M" DateOfBirth="1990-03-04" /> ' g.4=' <Student Name="Chad" Gender="M" DateOfBirth="1991-05-06" /> ' g.5=' <Student Name="Dave" Gender="M" DateOfBirth="1992-07-08"> ' g.6=' <Pet Type="dog" Name="Rover" /> ' g.7=' </Student> ' g.8=' <Student DateOfBirth="1993-09-10" Gender="F" Name="Émily" /> ' g.9='</Students> '
do j=1 while g.j\== g.j=space(g.j) parse var g.j 'Name="' studname '"' if studname\== then say studname end /*j*/ /*stick a fork in it, we're done.*/</lang>
output <lang rexx>April Bob Chad Dave Rover Émily</lang>
version 2
Some older REXXes don't have the changestr bif, so that's include here. <lang rexx>/*REXX program to extract student names from an XML string(s). */ g.= g.1='<Students> ' g.2=' <Student Name="April" Gender="F" DateOfBirth="1989-01-02" /> ' g.3=' <Student Name="Bob" Gender="M" DateOfBirth="1990-03-04" /> ' g.4=' <Student Name="Chad" Gender="M" DateOfBirth="1991-05-06" /> ' g.5=' <Student Name="Dave" Gender="M" DateOfBirth="1992-07-08"> ' g.6=' <Pet Type="dog" Name="Rover" / > ' g.7=' </Student> ' g.8=' <Student DateOfBirth="1993-09-10" Gender="F" Name="Émily" /> ' g.9='</Students> '
do j=1 while g.j\== g.j=space(g.j) parse var g.j 'Name="' studname '"' if studname== then iterate if pos('&',studname)\==0 then studname=xmlTranE(studname) say studname end /*j*/
exit /*stick a fork in it, we're done.*/ /*──────────────────────────────────CHANGESTR subroutine────────────────*/ changestr: procedure; parse arg o,h,n; r=; w=length(o); if w==0 then return n||h do forever; parse var h y (o) _ +(w) h; if _== then return r||y; r=r||y||n; end /*──────────────────────────────────XML_ subroutine─────────────────────*/ xml_: parse arg ,_ /*tran an XML entity (&xxxx;) */ xmlEntity! = '&'_";" if pos(xmlEntity!,x)\==0 then x=changestr(xmlEntity!,x,arg(1)) if left(_,2)=='#x' then do
xmlEntity!='&'left(_,3)translate(substr(_,4))";" x=changestr(xmlEntity!,x,arg(1)) end
return x /*──────────────────────────────────XMLTRANE subroutine─────────────────*/ xmlTranE: procedure; parse arg x /*Following are most of the chars in*/
/*the DOS (under Windows) codepage. */
x=XML_('♥',"hearts") ; x=XML_('â',"ETH") ; x=XML_('ƒ',"fnof") ; x=XML_('═',"boxH") x=XML_('♦',"diams") ; x=XML_('â','#x00e2') ; x=XML_('á',"aacute"); x=XML_('╬',"boxVH") x=XML_('♣',"clubs") ; x=XML_('â','#x00e9') ; x=XML_('á','#x00e1'); x=XML_('╧',"boxHu") x=XML_('♠',"spades") ; x=XML_('ä',"auml") ; x=XML_('í',"iacute"); x=XML_('╨',"boxhU") x=XML_('♂',"male") ; x=XML_('ä','#x00e4') ; x=XML_('í','#x00ed'); x=XML_('╤',"boxHd") x=XML_('♀',"female") ; x=XML_('à',"agrave") ; x=XML_('ó',"oacute"); x=XML_('╥',"boxhD") x=XML_('☼',"#x263c") ; x=XML_('à','#x00e0') ; x=XML_('ó','#x00f3'); x=XML_('╙',"boxUr") x=XML_('↕',"UpDownArrow") ; x=XML_('å',"aring") ; x=XML_('ú',"uacute"); x=XML_('╘',"boxuR") x=XML_('¶',"para") ; x=XML_('å','#x00e5') ; x=XML_('ú','#x00fa'); x=XML_('╒',"boxdR") x=XML_('§',"sect") ; x=XML_('ç',"ccedil") ; x=XML_('ñ',"ntilde"); x=XML_('╓',"boxDr") x=XML_('↑',"uarr") ; x=XML_('ç','#x00e7') ; x=XML_('ñ','#x00f1'); x=XML_('╫',"boxVh") x=XML_('↑',"uparrow") ; x=XML_('ê',"ecirc") ; x=XML_('Ñ',"Ntilde"); x=XML_('╪',"boxvH") x=XML_('↑',"ShortUpArrow") ; x=XML_('ê','#x00ea') ; x=XML_('Ñ','#x00d1'); x=XML_('┘',"boxul") x=XML_('↓',"darr") ; x=XML_('ë',"euml") ; x=XML_('¿',"iquest"); x=XML_('┌',"boxdr") x=XML_('↓',"downarrow") ; x=XML_('ë','#x00eb') ; x=XML_('⌐',"bnot") ; x=XML_('█',"block") x=XML_('↓',"ShortDownArrow") ; x=XML_('è',"egrave") ; x=XML_('¬',"not") ; x=XML_('▄',"lhblk") x=XML_('←',"larr") ; x=XML_('è','#x00e8') ; x=XML_('½',"frac12"); x=XML_('▀',"uhblk") x=XML_('←',"leftarrow") ; x=XML_('ï',"iuml") ; x=XML_('½',"half") ; x=XML_('α',"alpha") x=XML_('←',"ShortLeftArrow") ; x=XML_('ï','#x00ef') ; x=XML_('¼',"frac14"); x=XML_('ß',"beta") x=XML_('1c'x,"rarr") ; x=XML_('î',"icirc") ; x=XML_('¡',"iexcl") ; x=XML_('ß',"szlig") x=XML_('1c'x,"rightarrow") ; x=XML_('î','#x00ee') ; x=XML_('«',"laqru") ; x=XML_('ß','#x00df') x=XML_('1c'x,"ShortRightArrow"); x=XML_('ì',"igrave") ; x=XML_('»',"raqru") ; x=XML_('Γ',"Gamma") x=XML_('!',"excl") ; x=XML_('ì','#x00ec') ; x=XML_('░',"blk12") ; x=XML_('π',"pi") x=XML_('"',"apos") ; x=XML_('Ä',"Auml") ; x=XML_('▒',"blk14") ; x=XML_('Σ',"Sigma") x=XML_('$',"dollar") ; x=XML_('Ä','#x00c4') ; x=XML_('▓',"blk34") ; x=XML_('σ',"sigma") x=XML_("'","quot") ; x=XML_('Å',"Aring") ; x=XML_('│',"boxv") ; x=XML_('µ',"mu") x=XML_('*',"ast") ; x=XML_('Å','#x00c5') ; x=XML_('┤',"boxvl") ; x=XML_('τ',"tau") x=XML_('/',"sol") ; x=XML_('É',"Eacute") ; x=XML_('╡',"boxvL") ; x=XML_('Φ',"phi") x=XML_(':',"colon") ; x=XML_('É','#x00c9') ; x=XML_('╢',"boxVl") ; x=XML_('Θ',"Theta") x=XML_('<',"lt") ; x=XML_('æ',"aelig") ; x=XML_('╖',"boxDl") ; x=XML_('δ',"delta") x=XML_('=',"equals") ; x=XML_('æ','#x00e6') ; x=XML_('╕',"boxdL") ; x=XML_('∞',"infin") x=XML_('>',"gt") ; x=XML_('Æ',"AElig") ; x=XML_('╣',"boxVL") ; x=XML_('φ',"Phi") x=XML_('?',"quest") ; x=XML_('Æ','#x00c6') ; x=XML_('║',"boxV") ; x=XML_('ε',"epsilon") x=XML_('@',"commat") ; x=XML_('ô',"ocirc") ; x=XML_('╗',"boxDL") ; x=XML_('∩',"cap") x=XML_('[',"lbrack") ; x=XML_('ô','#x00f4') ; x=XML_('╝',"boxUL") ; x=XML_('≡',"equiv") x=XML_('\',"bsol") ; x=XML_('ö',"ouml") ; x=XML_('╜',"boxUl") ; x=XML_('±',"plusmn") x=XML_(']',"rbrack") ; x=XML_('ö','#x00f6') ; x=XML_('╛',"boxuL") ; x=XML_('±',"pm") x=XML_('^',"Hat") ; x=XML_('ò',"ograve") ; x=XML_('┐',"boxdl") ; x=XML_('±',"PlusMinus") x=XML_('`',"grave") ; x=XML_('ò','#x00f2') ; x=XML_('└',"boxur") ; x=XML_('≥',"ge") x=XML_('{',"lbrace") ; x=XML_('û',"ucirc") ; x=XML_('┴',"bottom"); x=XML_('≤',"le") x=XML_('{',"lcub") ; x=XML_('û','#x00fb') ; x=XML_('┴',"boxhu") ; x=XML_('÷',"div") x=XML_('|',"vert") ; x=XML_('ù',"ugrave") ; x=XML_('┬',"boxhd") ; x=XML_('÷',"divide") x=XML_('|',"verbar") ; x=XML_('ù','#x00f9') ; x=XML_('├',"boxvr") ; x=XML_('≈',"approx") x=XML_('}',"rbrace") ; x=XML_('ÿ',"yuml") ; x=XML_('─',"boxh") ; x=XML_('∙',"bull") x=XML_('}',"rcub") ; x=XML_('ÿ','#x00ff') ; x=XML_('┼',"boxvh") ; x=XML_('°',"deg") x=XML_('Ç',"Ccedil") ; x=XML_('Ö',"Ouml") ; x=XML_('╞',"boxvR") ; x=XML_('·',"middot") x=XML_('Ç','#x00c7') ; x=XML_('Ö','#x00d6') ; x=XML_('╟',"boxVr") ; x=XML_('·',"middledot") x=XML_('ü',"uuml") ; x=XML_('Ü',"Uuml") ; x=XML_('╚',"boxUR") ; x=XML_('·',"centerdot") x=XML_('ü','#x00fc') ; x=XML_('Ü','#x00dc') ; x=XML_('╔',"boxDR") ; x=XML_('·',"CenterDot") x=XML_('é',"eacute") ; x=XML_('¢',"cent") ; x=XML_('╩',"boxHU") ; x=XML_('√',"radic") x=XML_('é','#x00e9') ; x=XML_('£',"pound") ; x=XML_('╦',"boxHD") ; x=XML_('²',"sup2") x=XML_('â',"acirc") ; x=XML_('¥',"yen") ; x=XML_('╠',"boxVR") ; x=XML_('■',"squart ") return x</lang> output
April Bob Chad Dave Rover Émily
Ruby
<lang ruby>require 'rexml/document' include REXML
doc = Document.new(File.new("sample.xml"))
- or
- doc = Document.new(xml_string)
- without using xpath
doc.each_recursive do |node|
puts node.attributes["Name"] if node.name == "Student"
end
- using xpath
doc.each_element("*/Student") {|node| puts node.attributes["Name"]}</lang>
Scala
Scala has native XML support, with query constructs similar to XPath and XQuery.
<lang scala>val students =
<Students> <Student Name="April" Gender="F" DateOfBirth="1989-01-02" /> <Student Name="Bob" Gender="M" DateOfBirth="1990-03-04" /> <Student Name="Chad" Gender="M" DateOfBirth="1991-05-06" /> <Student Name="Dave" Gender="M" DateOfBirth="1992-07-08"> <Pet Type="dog" Name="Rover" /> </Student> <Student DateOfBirth="1993-09-10" Gender="F" Name="Émily" /> </Students>
students \ "Student" \\ "@Name" foreach println</lang>
Slate
Slate's XML Reader is still being developed at the time of this writing.
<lang slate>slate[1]> [ |tree|
tree: (Xml SimpleParser newOn: '<Students> <Student Name="April" Gender="F" DateOfBirth="1989-01-02" /> <Student Name="Bob" Gender="M" DateOfBirth="1990-03-04" /> <Student Name="Chad" Gender="M" DateOfBirth="1991-05-06" /> <Student Name="Dave" Gender="M" DateOfBirth="1992-07-08"> <Pet Type="dog" Name="Rover" /> </Student> <Student DateOfBirth="1993-09-10" Gender="F" Name="Émily" /> </Students>') parse. tree name = 'Students' ifTrue: [(tree children select: #is: `er <- Xml Element) do: [|:child| child name = 'Student' ifTrue: [inform: (child attributes at: 'Name' ifAbsent: ['Noname'])]]].
] do. April Bob Chad Dave Émily Nil</lang>
Tcl
Using
<lang tcl>package require tdom set tree [dom parse $xml] set studentNodes [$tree getElementsByTagName Student] ;# or: set studentNodes [[$tree documentElement] childNodes]
foreach node $studentNodes {
puts [$node getAttribute Name]
}</lang>
Using
<lang tcl>package require xml set parser [xml::parser -elementstartcommand elem] proc elem {name attlist args} {
if {$name eq "Student"} { puts [dict get $attlist Name] }
} $parser parse $xml</lang>
Using just pure-Tcl (originally on http://wiki.tcl.tk/3919): <lang Tcl>proc xml2list xml {
regsub -all {>\s*<} [string trim $xml " \n\t<>"] "\} \{" xml set xml [string map {> "\} \{#text \{" < "\}\} \{"} $xml] set res "" ;# string to collect the result set stack {} ;# track open tags set rest {} foreach item "{$xml}" { switch -regexp -- $item {
^# {append res "{[lrange $item 0 end]} " ; #text item} ^/ { regexp {/(.+)} $item -> tagname ;# end tag set expected [lindex $stack end] set stack [lrange $stack 0 end-1] append res "\}\} "
}
/$ { # singleton - start and end in one <> group
regexp {([^ ]+)( (.+))?/$} $item -> tagname - rest set rest [lrange [string map {= " "} $rest] 0 end] append res "{$tagname [list $rest] {}} "
} default {
set tagname [lindex $item 0] ;# start tag set rest [lrange [string map {= " "} $item] 1 end] lappend stack $tagname append res "\{$tagname [list $rest] \{"
}
} } string map {"\} \}" "\}\}"} [lindex $res 0] ;#"
} proc deent str {
regsub -all {&\#x(.+?);} $str {\\u\1} str subst -nocommands -novar $str
}
- ----------------------- Testing the whole thing:
set xml {<Students>
<Student Name="April" Gender="F" DateOfBirth="1989-01-02" /> <Student Name="Bob" Gender="M" DateOfBirth="1990-03-04" /> <Student Name="Chad" Gender="M" DateOfBirth="1991-05-06" /> <Student Name="Dave" Gender="M" DateOfBirth="1992-07-08"> <Pet Type="dog" Name="Rover" /> </Student> <Student DateOfBirth="1993-09-10" Gender="F" Name="Émily" /></Students>
} foreach i [lindex [xml2list $xml] 2] {
if {[lindex $i 0] eq "Student"} { foreach {att val} [lindex $i 1] { if {$att eq "Name"} {puts [deent $val]} } }
}</lang>
TUSCRIPT
<lang tuscript> $$ MODE TUSCRIPT MODE DATA $$ SET xmldata =* <Students>
<Student Name="April" Gender="F" DateOfBirth="1989-01-02" /> <Student Name="Bob" Gender="M" DateOfBirth="1990-03-04" /> <Student Name="Chad" Gender="M" DateOfBirth="1991-05-06" /> <Student Name="Dave" Gender="M" DateOfBirth="1992-07-08"> <Pet Type="dog" Name="Rover" /> </Student> <Student DateOfBirth="1993-09-10" Gender="F" Name="Emily" />
</Students> $$ MODE TUSCRIPT COMPILE LOOP x = xmldata SET name=GET_TAG_NAME (x) IF (name=="student") THEN SET studentname=GET_ATTRIBUTE (x,"Name") IF (studentname!="") PRINT studentname ENDIF ENDLOOP ENDCOMPILE </lang> Output:
April Bob Chad Dave Emily
TXR
This program shows how most of the information in the XML can be extracted with very little code, which doesn't actually understand XML. The name Émily is properly converted from the HTML/XML escape syntax.
<lang txr><Students> @(collect :vars (NAME GENDER YEAR MONTH DAY (PET_TYPE "none") (PET_NAME ""))) @ (cases)
<Student Name="@NAME" Gender="@GENDER" DateOfBirth="@YEAR-@MONTH-@DAY"@(skip)
@ (or)
<Student DateOfBirth="@YEAR-@MONTH-@DAY" Gender="@GENDER" Name="@NAME"@(skip)
@ (end) @ (maybe)
<Pet Type="@PET_TYPE" Name="@PET_NAME" />
@ (end) @(until) </Students> @(end) @(output :filter :from_html) NAME G DOB PET @ (repeat) @{NAME 12} @GENDER @YEAR-@MONTH-@DAY @PET_TYPE @PET_NAME @ (end) @(end)</lang>
Sample run:
$ txr students.txr students.xml NAME G DOB PET April F 1989-01-02 none Bob M 1990-03-04 none Chad M 1991-05-06 none Dave M 1992-07-08 dog Rover Émily F 1993-09-10 none
To obtain the output specified in this task, we can simply reduce the @(output) block to this:
<lang txr>@(output :filter :from_html) @NAME @(end)</lang>
April Bob Chad Dave Émily
Vedit macro language
This implementation finds all Student tags and then displays the contents of their Name parameter. <lang vedit>Repeat(ALL) {
Search("<Student|X", ERRBREAK) #1 = Cur_Pos Match_Paren() if (Search_Block(/Name=|{",'}/, #1, Cur_Pos, BEGIN+ADVANCE+NOERR+NORESTORE)==0) { Continue } #2 = Cur_Pos Search(/|{",'}/) Type_Block(#2, Cur_Pos) Type_Newline
}</lang>
Output:
April Bob Chad Dave Émily
Visual Basic .NET
<lang vbnet>Dim xml = <Students>
<Student Name="April"/> <Student Name="Bob"/> <Student Name="Chad"/> <Student Name="Dave"/> <Student Name="Emily"/> </Students>
Dim names = (From node In xml...<Student> Select node.@Name).ToArray
For Each name In names
Console.WriteLine(name)
Next</lang>
XPL0
<lang XPL0>code ChOut=8, CrLf=9; \intrinsic routines string 0; \use zero-terminated strings
func StrLen(A); \Return number of characters in an ASCIIZ string char A; int I; for I:= 0 to -1>>1-1 do
if A(I) = 0 then return I;
func StrFind(A, B); \Search for ASCIIZ string A in string B \Returns address of first occurrence of string A in B, or zero if A is not found char A, B; \strings to be compared int LA, LB, I, J; [LA:= StrLen(A); LB:= StrLen(B); for I:= 0 to LB-LA do
[for J:= 0 to LA-1 do if A(J) # B(J+I) then J:= LA+1; if J = LA then return B+I; \found ];
return 0; ];
char XML, P; [XML:= "<Students>
<Student Name=^"April^" Gender=^"F^" DateOfBirth=^"1989-01-02^" /> <Student Name=^"Bob^" Gender=^"M^" DateOfBirth=^"1990-03-04^" /> <Student Name=^"Chad^" Gender=^"M^" DateOfBirth=^"1991-05-06^" /> <Student Name=^"Dave^" Gender=^"M^" DateOfBirth=^"1992-07-08^"> <Pet Type=^"dog^" Name=^"Rover^" /> </Student> <Student DateOfBirth=^"1993-09-10^" Gender=^"F^" Name=^"Émily^" /> </Students>";
P:= XML; loop [P:= StrFind("<Student ", P);
if P=0 then quit; P:= StrFind("Name=", P); if P=0 then quit; P:= P + StrLen("Name=x"); repeat ChOut(0, P(0)); P:= P+1; until P(0) = ^"; CrLf(0); ];
]</lang>
- Output:
April Bob Chad Dave Émily
- Programming Tasks
- XML
- ActionScript
- Ada
- Aikido
- AutoHotkey
- AWK
- BBC BASIC
- C
- LibXML
- Libxml
- C Runtime
- C++
- Qt
- C sharp
- Clojure
- Java.io
- Clojure.xml
- Common Lisp
- Closure XML
- D
- KXML
- Delphi
- Factor
- Fantom
- Forth
- Forth Foundation Library
- Go
- Groovy
- Haskell
- HicEst
- J
- Java
- Org.xml.sax
- JavaScript
- Lua
- Mathematica
- NewLISP
- Objeck
- OCaml
- OpenEdge/Progress
- Oz
- Perl
- PHP
- PicoLisp
- Pike
- PowerShell
- OpenEdge ABL/Progress 4GL
- PureBasic
- Python
- R
- Rascal
- REBOL
- REXX
- Ruby
- REXML
- Scala
- Slate
- Slate examples needing attention
- Examples needing attention
- Tcl
- TDOM
- TclXML
- TUSCRIPT
- TXR
- Vedit macro language
- Visual Basic .NET
- XPL0
- GUISS/Omit
- PARI/GP/Omit