XML/Input

From Rosetta Code

< XML(Redirected from XML Reading)
Jump to: navigation, search
Task
XML/Input
You are encouraged to solve this task according to the task description, using any language you may know.

Given the below 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.

<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="&#x00C9;mily" />
</Students>

Expected Output

April
Bob
Chad
Dave
Émily

Contents

[edit] 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);
}
}
}
}

[edit] Aikido

Put the XML in the file called t.xml

 
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"))
}
}
}
}
 
 

The output is (Aikido doesn't support unicode rendering):

April
Bob
Chad
Dave
Émily

[edit] AutoHotkey

simply using regular expressions

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="&#x00C9;mily" />
</Students>
)
 
quote = " ; "
pos = 1
while, pos := RegExMatch(students, "Name=.(\w+)" . quote . "\sGender"
, name, pos + 1)
names .= name1 . "`n"
 
msgbox % names

[edit] 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.

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

Using getXML.awk written by Jan Weber, one could do this:

Works with: gawk or Works with: nawk

awk -f getXML.awk sample.xml | awk '
$1 == "TAG" {tag = $2}
tag == "Student" && /Name=/ {print substr($0, index($0, "=") + 1)}
'

Using xmlparser.awk by Steve Coile, one can do this:

Works with: gawk

gawk -f xmlparser.awk sample.xml | awk '
$1 == "begin" {tag = $2}
$1 == "attrib" {attrib = $2}
$1 == "value" && tag == "STUDENT" && attrib == "name" {print $2}
'

Both of these produce this output

April
Bob
Chad
Dave
&#x00C9;mily

Works with: XMLgawk

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

[edit] C

Library: LibXML

#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=\"&#x00C9;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;
}

[edit] C++

Library: Qt

/*
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=\"&#x00C9;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;
}

[edit] C#

 
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();
}
}
 

[edit] Clojure

This version uses the standard Clojure function xml-seq and standard library function clojure.xml/parse.

 
(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='&#x00C9;mily' />
</Students>"
)
 
(def students (parse (-> xml-text .getBytes ByteArrayInputStream.)))
 

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.

 
(doseq [{:keys [tag attrs]} (xml-seq students)]
(if (= :Student tag)
(println (:Name attrs))))
 

[edit] Common Lisp

Library: Closure XML

(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=\"&#x00C9;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))))
produces
("April" "Bob" "Chad" "Dave" "Émily")

[edit] D

Library: KXML

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=\"&#x00C9;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;
}
}

[edit] 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="&#x00C9;mily" />
</Students>""" print-student-names

[edit] Go

Go's xml.Unmarshal uses reflection to fill in data-structures recursively.

package main
 
import (
"xml"
"strings"
)
 
type Students struct {
Student []Student
}
 
type Student struct {
Name string "attr"
Gender string "attr"
DateOfBirth string "attr"
Pet []Pet
}
 
type Pet struct {
Type string "attr"
Name string "attr"
}
 
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="&#x00C9;mily" />
</Students>
`

 
func main() {
data := new(Students)
err := xml.Unmarshal(strings.NewReader(XML_DATA), data)
if err != nil { panic(err) }
for _, s := range data.Student {
println(s.Name)
}
}

Output:

April
Bob
Chad
Dave
Émily

[edit] 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=\"&#x00C9;mily\" />"++
"</Students>"
 
xmlRead elm name = mapM_ putStrLn
. concatMap (map (fromJust.findAttr (unqual name)).filterElementsName (== unqual elm))
. onlyElems. parseXML

Show names:

*Main> xmlRead "Student" "Name" students
April
Bob
Chad
Dave
Émily

[edit] HicEst

CHARACTER in*1000, out*100
 
READ(ClipBoard) in
EDIT(Text=in, SPR='"', Right='<Student', Right='Name=', Word=1, WordEnd, APpendTo=out, DO)
out is returned as:
April  Bob  Chad  Dave  Émily

[edit] 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:

load'xml/sax'
 
saxclass 'Students'
startElement =: ([: smoutput 'Name' getAttribute~ [)^:('Student'-:])
cocurrent'base'
 
process_Students_ XML
April
Bob
Chad
Dave
Émily

and the definition of XML:

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="&#x00C9;mily" />
</Students>
)

[edit] 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=\"&#x00C9;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"));
}
}
}

[edit] JavaScript

This version tested against Chrome 5, Firefox 3.6, and IE 8:

 
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="&#x00C9;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);
 

Works with: Mozilla Firefox version 3.6

Alternatively, use the E4X featureset (currently only in Firefox):

 
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="&#x00C9;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);
 

[edit] OCaml

from the toplevel using the library xml-light:

# #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='&#x00C9;mily' />
</Students>"

in
Xml.iter (function
Xml.Element ("Student", attrs, _) ->
List.iter (function ("Name", name) -> print_endline name | _ -> ()) attrs
| _ -> ()) x
;;
April
Bob
Chad
Dave
&#x00C9;mily
- : unit = ()

Another solution using the library xmlm:

#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='&#x00C9;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

using the ocaml expat wrapper:

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='&#x00C9;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;

[edit] 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=\"&#x00C9;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}

[edit] Perl

Library: XML::SimpleSimple

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="&#x00C9;mily" />
</Students>'
);
 
print join( "\n", map { $_->{'Name'} } @{$ref->{'Student'}});

[edit] 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="&#x00C9;mily" />
</Students>'
;
$xml = new XMLReader();
$xml->xml( $data );
while ( $xml->read() )
if ( XMLREADER::ELEMENT == $xml->nodeType && $xml->localName == 'Student' )
echo $xml->getAttribute('Name') . "\n";
?>

[edit] PicoLisp

(load "@lib/xm.l")
 
(mapcar
'((L) (attr L 'Name))
(body (in "file.xml" (xml))) )

Output:

-> ("April" "Bob" "Chad" "Dave" "Émily")

[edit] PureBasic

Uses a PureBasic XML library (which is linked automatically) that is based on the library expat XML parser licensed under the MIT license.

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='&#x00C9;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

Sample output:

April
Bob
Chad
Dave
Émily

[edit] 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="&#x00C9;mily" />
</Students>"""

 
doc = xml.dom.minidom.parseString(doc)
 
for i in doc.getElementsByTagName("Student"):
print i.getAttribute("Name")

[edit] R

Library: XML

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="&#x00C9;mily" />
</Students>'))
close(tc)
str
[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>"
#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
[1] "April" "Bob"   "Chad"  "Dave"  "Émily"

[edit] 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="&#x00C9;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"
]
]

Output:

April
Bob
Chad
Dave
Émily

[edit] Ruby

Library: REXML

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"]}

[edit] Scala

Scala has native XML support, with query constructs similar to XPath and XQuery.

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="&#x00C9;mily" />
</Students>
 
students \ "Student" \\ "@Name" foreach println

Result:

April
Bob
Chad
Dave
Rover
Émily

[edit] Slate

Some lines in this example are too long (more than 80 characters). Please fix the code if it's possible and remove this message.

Slate's XML Reader is still being developed at the time of this writing.

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="&#x00C9;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
&#x00C9;mily
Nil

[edit] Tcl

Using Library: tDOM

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

Using Library: TclXML

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

Using just pure-Tcl (originally on http://wiki.tcl.tk/3919):

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="&#x00C9;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]}
}
}
}

[edit] Vedit macro language

This implementation finds all Student tags and then displays the contents of their Name parameter.

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
}

Output:

April
Bob
Chad
Dave
Émily

[edit] Visual Basic .NET

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
Personal tools
Support