View Category
Process an XML document
Given the XML Document:
<shopping>
<item name=
<item name=
</shopping>
Print out the total cost of the items, e.g. $14.50
<shopping>
<item name=
"bread" quantity="3" price="2.50"/>
<item name=
"milk" quantity="2" price="3.50"/>
</shopping>
Print out the total cost of the items, e.g. $14.50
ruby
#!/usr/bin/env ruby
# needed to parse xml
require 'rexml/document'
# grab the file
file = File.new('shop.xml')
# load it as an xml document
doc = REXML::Document.new(file)
# initialize the total to 0 as a float
total = 0.0
# cycle through the items
doc.elements.each('shopping/item') do |item|
# add the price to the total
total += item.attributes['price'].to_f
end
# round the total to the nearest 0.01
total = (total*100.0).round/100.0
# pad the output with the proper number of trailing 0's
printf "$%.2f\n", total
# needed to parse xml
require 'rexml/document'
# grab the file
file = File.new('shop.xml')
# load it as an xml document
doc = REXML::Document.new(file)
# initialize the total to 0 as a float
total = 0.0
# cycle through the items
doc.elements.each('shopping/item') do |item|
# add the price to the total
total += item.attributes['price'].to_f
end
# round the total to the nearest 0.01
total = (total*100.0).round/100.0
# pad the output with the proper number of trailing 0's
printf "$%.2f\n", total
cpp
char input[] =
"<shopping>"
" <item name=\"bread\" quantity=\"3\" price=\"2.50\"/>"
" <item name=\"milk\" quantity=\"2\" price=\"3.50\"/>"
"</shopping>";
xml_document<> doc;
doc.parse<0>(input);
xml_node<> *shopping = doc.first_node();
float total_price = 0;
for (xml_node<> *item = shopping->first_node(); item != NULL; item = item->next_sibling())
{
float item_sum = 0;
float val;
if (string(item->name()) != "item")
continue;
for (xml_attribute<> *attr = item->first_attribute(); attr != NULL; attr = attr->next_attribute())
{
string name(attr->name());
if (name == "quantity" || name == "price")
{
stringstream v(attr->value());
v >> val;
if (item_sum)
item_sum *= val;
else
item_sum = val;
}
}
total_price += item_sum;
}
cout.setf(ios::fixed, ios::floatfield);
cout << "Total price is $" << setprecision(2) << total_price << endl;
"<shopping>"
" <item name=\"bread\" quantity=\"3\" price=\"2.50\"/>"
" <item name=\"milk\" quantity=\"2\" price=\"3.50\"/>"
"</shopping>";
xml_document<> doc;
doc.parse<0>(input);
xml_node<> *shopping = doc.first_node();
float total_price = 0;
for (xml_node<> *item = shopping->first_node(); item != NULL; item = item->next_sibling())
{
float item_sum = 0;
float val;
if (string(item->name()) != "item")
continue;
for (xml_attribute<> *attr = item->first_attribute(); attr != NULL; attr = attr->next_attribute())
{
string name(attr->name());
if (name == "quantity" || name == "price")
{
stringstream v(attr->value());
v >> val;
if (item_sum)
item_sum *= val;
else
item_sum = val;
}
}
total_price += item_sum;
}
cout.setf(ios::fixed, ios::floatfield);
cout << "Total price is $" << setprecision(2) << total_price << endl;
fsharp
#r @"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\v3.5\System.Xml.Linq.dll"
open System
open System.Xml.Linq
//XElement Helper
let xname sname = XName.Get sname
let xmlsnippet =
let snippet = new XElement(xname "shopping")
//create bread
let bread = new XElement(xname "item")
bread.SetAttributeValue(xname "name","bread")
bread.SetAttributeValue(xname "quantity",3)
bread.SetAttributeValue(xname "price",2.50)
//add bread to snippet
snippet.Add(bread)
//create milk
let milk = new XElement(xname "item")
milk.SetAttributeValue(xname "name","milk")
milk.SetAttributeValue(xname "quantity",2)
milk.SetAttributeValue(xname "price",3.50)
//add milk to snippet
snippet.Add(milk)
snippet
let totalprice (xe: XElement) =
xe.Descendants(xname "item")
|> Seq.map(fun i -> Double.Parse(i.Attribute(xname "price").Value))
|> Seq.fold(fun acc x -> acc + x) 0.0
open System
open System.Xml.Linq
//XElement Helper
let xname sname = XName.Get sname
let xmlsnippet =
let snippet = new XElement(xname "shopping")
//create bread
let bread = new XElement(xname "item")
bread.SetAttributeValue(xname "name","bread")
bread.SetAttributeValue(xname "quantity",3)
bread.SetAttributeValue(xname "price",2.50)
//add bread to snippet
snippet.Add(bread)
//create milk
let milk = new XElement(xname "item")
milk.SetAttributeValue(xname "name","milk")
milk.SetAttributeValue(xname "quantity",2)
milk.SetAttributeValue(xname "price",3.50)
//add milk to snippet
snippet.Add(milk)
snippet
let totalprice (xe: XElement) =
xe.Descendants(xname "item")
|> Seq.map(fun i -> Double.Parse(i.Attribute(xname "price").Value))
|> Seq.fold(fun acc x -> acc + x) 0.0
let xname sname = XName.Get sname
let xattr (elem: XElement) sname = elem.Attribute(xname sname).Value
let xml = XDocument.Load("xml.txt")
let shoppingCost =
xml.Descendants(xname "item")
|> Seq.map (fun i -> Double.Parse(xattr i "quantity"), Double.Parse(xattr i "price"))
|> Seq.sumBy (fun (quantity, price) -> quantity * price)
let xattr (elem: XElement) sname = elem.Attribute(xname sname).Value
let xml = XDocument.Load("xml.txt")
let shoppingCost =
xml.Descendants(xname "item")
|> Seq.map (fun i -> Double.Parse(xattr i "quantity"), Double.Parse(xattr i "price"))
|> Seq.sumBy (fun (quantity, price) -> quantity * price)
// Alternative solution that uses XML Navigation, and XPath expressions to ensure that
// the items have the required attributes
let xname sname = XName.Get sname
let xattr (elem: XElement) sname = elem.Attribute(xname sname).Value
let navigator = XPathDocument("xml.txt").CreateNavigator()
let path = XPathExpression.Compile("/shopping/item[@price][@quantity]")
let names = XmlNamespaceManager(navigator.NameTable)
path.SetContext(names)
let shoppingCost =
match path.ReturnType with
| XPathResultType.NodeSet ->
navigator.Select(path)
|> Seq.cast
|> Seq.map (fun (i: XPathNavigator) ->
if i.IsNode then
let elem = XElement.Parse(i.OuterXml)
Double.Parse(xattr elem "quantity"), Double.Parse(xattr elem "price")
else
failwith "Error in expression, expecting to see a node"
)
|> Seq.sumBy (fun (quantity, price) -> quantity * price)
| _ -> failwith "Error in expression, expecting to see a node set"
// the items have the required attributes
let xname sname = XName.Get sname
let xattr (elem: XElement) sname = elem.Attribute(xname sname).Value
let navigator = XPathDocument("xml.txt").CreateNavigator()
let path = XPathExpression.Compile("/shopping/item[@price][@quantity]")
let names = XmlNamespaceManager(navigator.NameTable)
path.SetContext(names)
let shoppingCost =
match path.ReturnType with
| XPathResultType.NodeSet ->
navigator.Select(path)
|> Seq.cast
|> Seq.map (fun (i: XPathNavigator) ->
if i.IsNode then
let elem = XElement.Parse(i.OuterXml)
Double.Parse(xattr elem "quantity"), Double.Parse(xattr elem "price")
else
failwith "Error in expression, expecting to see a node"
)
|> Seq.sumBy (fun (quantity, price) -> quantity * price)
| _ -> failwith "Error in expression, expecting to see a node set"
csharp
System.Xml.XmlDocument doc = new System.Xml.XmlDocument();
doc.LoadXml(
@"<shopping>
<item name='bread' quantity='3' price='2.50'/>
<item name='milk' quantity='2' price='3.50'/>
</shopping>");
string decimalSeparator= System.Globalization.CultureInfo.CurrentCulture.NumberFormat.CurrencyDecimalSeparator;
double sum=0;
foreach(System.Xml.XmlNode nodo in doc.SelectNodes("/shopping/item")){
sum += int.Parse(nodo.Attributes["quantity"].InnerText) * double.Parse(nodo.Attributes["price"].InnerText.Replace(".",decimalSeparator));
}
Console.WriteLine("{0:#.00}",sum);
doc.LoadXml(
@"<shopping>
<item name='bread' quantity='3' price='2.50'/>
<item name='milk' quantity='2' price='3.50'/>
</shopping>");
string decimalSeparator= System.Globalization.CultureInfo.CurrentCulture.NumberFormat.CurrencyDecimalSeparator;
double sum=0;
foreach(System.Xml.XmlNode nodo in doc.SelectNodes("/shopping/item")){
sum += int.Parse(nodo.Attributes["quantity"].InnerText) * double.Parse(nodo.Attributes["price"].InnerText.Replace(".",decimalSeparator));
}
Console.WriteLine("{0:#.00}",sum);
fantom
sum := 0.0
root := XParser(File(`shop.xml`).in).parseDoc.root
if (root.name == "shopping")
{
root.elems.each
{
if (it.name == "item")
{
quantity := Int.fromStr(it.get("quantity"))
price := Decimal.fromStr(it.get("price"))
sum += quantity * price;
}
}
}
echo("\$$sum")
root := XParser(File(`shop.xml`).in).parseDoc.root
if (root.name == "shopping")
{
root.elems.each
{
if (it.name == "item")
{
quantity := Int.fromStr(it.get("quantity"))
price := Decimal.fromStr(it.get("price"))
sum += quantity * price;
}
}
}
echo("\$$sum")
create some XML programmatically
Given the following CSV:
bread,3,2.50
milk,2,3.50
Produce the equivalent information in XML, e.g.:
<shopping>
<item name=
<item name=
</shopping>
bread,3,2.50
milk,2,3.50
Produce the equivalent information in XML, e.g.:
<shopping>
<item name=
"bread" quantity="3" price="2.50" />
<item name=
"milk" quantity="2" price="3.50" />
</shopping>
ruby
# gem install builder
require 'builder'
xml = Builder::XmlMarkup.new
xml.shopping do
xml.item(:name => "bread", :quantity => 3, :price => "2.50")
xml.item(:name => "milk", :quantity => 2, :price => "3.50")
end
xml
require 'builder'
xml = Builder::XmlMarkup.new
xml.shopping do
xml.item(:name => "bread", :quantity => 3, :price => "2.50")
xml.item(:name => "milk", :quantity => 2, :price => "3.50")
end
xml
cpp
string input("bread,3,2.50\nmilk,2,3.50\n");
tokenizer<char_separator<char> > tokens(input, char_separator<char>(", \n"));
tokenizer<char_separator<char> >::iterator it = tokens.begin();
xml_document<> doc;
xml_node<> *shopping = doc.allocate_node(node_element, "shopping");
doc.append_node(shopping);
while (it != tokens.end()) {
xml_node<> *item = doc.allocate_node(node_element, "item");
shopping->append_node(item);
item->append_attribute(doc.allocate_attribute("name", doc.allocate_string((*it++).c_str())));
item->append_attribute(doc.allocate_attribute("quantity", doc.allocate_string((*it++).c_str())));
item->append_attribute(doc.allocate_attribute("price", doc.allocate_string((*it++).c_str())));
}
cout << doc << endl;
tokenizer<char_separator<char> > tokens(input, char_separator<char>(", \n"));
tokenizer<char_separator<char> >::iterator it = tokens.begin();
xml_document<> doc;
xml_node<> *shopping = doc.allocate_node(node_element, "shopping");
doc.append_node(shopping);
while (it != tokens.end()) {
xml_node<> *item = doc.allocate_node(node_element, "item");
shopping->append_node(item);
item->append_attribute(doc.allocate_attribute("name", doc.allocate_string((*it++).c_str())));
item->append_attribute(doc.allocate_attribute("quantity", doc.allocate_string((*it++).c_str())));
item->append_attribute(doc.allocate_attribute("price", doc.allocate_string((*it++).c_str())));
}
cout << doc << endl;
fsharp
#r "System.Xml.dll"
#r "System.Xml.Linq.dll"
open System
open System.Xml
open System.Xml.Linq
let data = "bread,3,2.50
milk,2,3.50"
let X name =
XName.Get(name)
let lines = data.Split( [|"\n" |], StringSplitOptions.RemoveEmptyEntries)
let document = new XDocument()
let element = new XElement(X "shopping")
document.Add(element)
lines
|> Seq.iter (fun line ->
let items = line.Split([|','|])
let item = new XElement(X "item",
new XAttribute(X "name", items.[0]),
new XAttribute(X "quantity", items.[1]),
new XAttribute(X "price", items.[2]))
element.Add(item))
let output = document.ToString();;
#r "System.Xml.Linq.dll"
open System
open System.Xml
open System.Xml.Linq
let data = "bread,3,2.50
milk,2,3.50"
let X name =
XName.Get(name)
let lines = data.Split( [|"\n" |], StringSplitOptions.RemoveEmptyEntries)
let document = new XDocument()
let element = new XElement(X "shopping")
document.Add(element)
lines
|> Seq.iter (fun line ->
let items = line.Split([|','|])
let item = new XElement(X "item",
new XAttribute(X "name", items.[0]),
new XAttribute(X "quantity", items.[1]),
new XAttribute(X "price", items.[2]))
element.Add(item))
let output = document.ToString();;
csharp
string cvs ="bread,3,2.50\nmilk,2,3.50";
IList<string> rows = cvs.Split('\n');
System.Text.StringBuilder sb = new System.Text.StringBuilder("<shopping>");
foreach(string row in rows){
IList<string> data = row.Split(',');
sb.AppendFormat("<item name='{0}' quantity='{1}' price='{2}' />",data[0],data[1],data[2]);
}
sb.Append("</shopping>");
IList<string> rows = cvs.Split('\n');
System.Text.StringBuilder sb = new System.Text.StringBuilder("<shopping>");
foreach(string row in rows){
IList<string> data = row.Split(',');
sb.AppendFormat("<item name='{0}' quantity='{1}' price='{2}' />",data[0],data[1],data[2]);
}
sb.Append("</shopping>");
fantom
sum := 0.0
rows := CsvInStream(File(`shop.csv`).in).readAllRows
doc := XDoc()
doc.root = XElem("shopping")
{
root := it
rows.each |Str[] row|
{
root.add(XElem("item")
{
XAttr("name", row[0]),
XAttr("quantity", row[1]),
XAttr("price", row[2])
})
}
}
os := File(`shop.xml`).out
doc.write(os)
os.close
rows := CsvInStream(File(`shop.csv`).in).readAllRows
doc := XDoc()
doc.root = XElem("shopping")
{
root := it
rows.each |Str[] row|
{
root.add(XElem("item")
{
XAttr("name", row[0]),
XAttr("quantity", row[1]),
XAttr("price", row[2])
})
}
}
os := File(`shop.xml`).out
doc.write(os)
os.close
