PHP simple XML parsing

January 12th, 2010

Little example of using PHP and XPath to grab values from simplistic XML structure. Requires PHP5+


<?
// the xml would be read somewhere, or sent in the request
$xml = <<<XML
<order>
<header>
<transactionDate>01/01/2010</transactionDate>
<client>elmer fudd</client>
</header>
<defendants>
<defendant>
<name>Bugs Bunny</name>
<addresses>
<address>
<line1>555 Elm Street</line1>
<line2 />
<city>Elk Grove</city>
<state>IL</state>
<zip>55555</zip>
</address>
<address>
<line1>555 Lake Shore Dr</line1>
<line2>Apt 201</line2>
<city>Chicago</city>
<state>IL</state>
<zip>55555</zip>
</address>
</addresses>
</defendant>
<defendant>
<name>Daffy Duck</name>
<addresses>
<address>
<line1>555 Elm Street</line1>
<line2 />
<city>Elk Grove</city>
<state>IL</state>
<zip>55555</zip>
</address>
</addresses>
</defendant>
</defendants>
</order>
XML;

$xmlDoc = new SimpleXMLElement($xml);
($transactionDate = $xmlDoc->xpath('/order/header/transactionDate')) || die ('invalid: missing transaction date');
echo 'Transaction Date: ' . $transactionDate[0] . '<br/>';

$nodes = $xmlDoc->xpath('/order/defendants/defendant');
foreach ($nodes as $node)
{
//print_r($node);
echo '<br>';
echo $node->name . '<br/>';
//print_r($node->addresses);
foreach($node->addresses->address as $addr)
{
echo $addr->line1 . '<br/>';
echo $addr->line2 . '<br/>';
echo $addr->city . '<br/>';
echo $addr->state . '<br/>';
echo $addr->zip . '<br/>';
}

}

?>

Using XSLT For Dynamic Content

April 20th, 2009

I read this post on XSLT and dynamic content in ASP.NET, and at the time, I didn’t think it applied to anything I did. I’m always willing to experiment with new code and I do try to be open minded about implementation, though.

It struck me that the author’s comment on when to use this design never applies to me for the applications I work with daily:

“Best suited for applications with high data complexity and ones that are expected to change significantly and frequently. In addition, this allows for a lot of room for creativity as far as interface design goes.”

Also, in the example code, there are no server controls (at least not that I saw). There isn’t a single application I’ve ever done in ASP.NET that didn’t need to postback and manipulate controls, check what the user entered, and so on. So, I filed the idea for later.

I bring this up because when I was trolling the asp.net forums for an idea for a post and saw what looked like a pretty easy question on how to implement a simple trivia question/answer page, I thought I could get some practice with a few different ideas, including this one – the idea of generating content and controls with transformations.

This post is the result of my deciding to play. I won’t say it’s the best way to implement it, only that it is A way to do so. I wanted to use VB.NET (after a blurb in a post on another site mentioned how few good examples are available in the language) and XSLT transforms and not rely on a database like I normally do, and I wanted to see if I could use XSLT and server controls together, so I used this idea of a little trivia to do that.

Read the rest of this entry »

XML Serialization and List

January 25th, 2009

I was writing a small wrapper class to consume a third party XML response from a web service. Using a little helper class is a lot easier than playing with DOM. One of the elements was an Errors element that could have multiple Error child elements, like so:


<Errors>
   <Error>detail</Error>
   <Error>detail</Error>
</Errors>

In my class, I wanted to use a List<string> to account for this, but since I was consuming XML, I needed to be able to tell it the element name, otherwise it serializes and deserializes as just “string”, like this.


<?xml version="1.0" encoding="utf-16"?>
<WebServiceResponse xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<statusCode>failure</statusCode>
<recordsAffected>0</recordsAffected>
<Errors>
   <string>Foo</string>
</Errors>
</WebServiceResponse>

 

So when I tried to read in the xml, I got an error because it couldn’t find an Error element (it was string). Not so helpful.

I needed the ElementName property in my class.

[XmlArrayItem(typeof(string), ElementName = "Error")]
public List<string> Errors;

Adding this, the element was correctly deserialized so it could read something like this.


<?xml version="1.0" encoding="utf-16"?>
<WebServiceResponse xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<statusCode>failure</statusCode>
<recordsAffected>0</recordsAffected>
<Errors>
   <Error>Foo</Error>
</Errors>
</WebServiceResponse>

Here is some code to play with so you can try it out and see how the attribute affects serialization and deserialization. Have fun!


using System;
using System.Collections.Generic;
using System.Xml.Serialization;
using System.IO;
using System.Text;

namespace ConsoleApplication1
{
    public class Program
    {
        public class WebServiceResponse
        {
            public string statusCode;
            public string recordsAffected;

            [XmlArrayItem(typeof(string), ElementName = "Error")]
            public List<string> Errors;
        }

        static void Main(string[] args)
        {
            // if we were to set the elements themselves, it could look like this
            WebServiceResponse r = new WebServiceResponse();
            r.statusCode = "success";
            r.recordsAffected = "1";
            r.Errors = new List<string>();
            r.Errors.Add("Foo");

            XmlSerializer serializer = new XmlSerializer(typeof(WebServiceResponse));
            StringBuilder sb = new StringBuilder();
            serializer.Serialize(new StringWriter(sb), r);
            Console.WriteLine(sb.ToString());

            string s = sb.ToString();
            // more likely, we'd be reading them in from an XML response to manipulate, like so
            // (you'd have the xml response from a web service in a string or such)
            TextReader sr = new StringReader(s);
            WebServiceResponse r2 = serializer.Deserialize(sr) as WebServiceResponse;
            int numErrors = r2.Errors == null ? 0 : r2.Errors.Count;
            Console.WriteLine("There were " + numErrors + " errors");

            Console.Read();
        }
    }
}

XML String into DataSet

December 19th, 2008

A particular query (a stored procedure, actually) I was stuck using returned XML from one of our legacy applications. It wasn’t pretty XML and didn’t work well with XmlDataSource, and XML DOM methods can be tedious. I found myself wishing I just had a DataSet. So I read it in as one.

In order to get the string results of the procedure into an untyped DataSet, I used ReadXml and a StringReader.


DataSet dataset = new DataSet();
dataset.ReadXml(new StringReader(xmlString));

You can grab a sample XML file called books.xml from Microsoft’s website here if you want to play and see how to work with what comes from ReadXml into an untyped, plain DataSet. A word of caution, though — books.xml is a well-formed and structured file and may be easier to work with than is typical of other people’s files.

There are other options, of course, depending on what works best for your application and data. You could read it into an XmlDocument and use XML methods (XPath and such), you could define a strongly typed dataset and read it into that, or you could use XmlDataSource. Play with your data and see what works best for it and your situation. Remember the rule — keep it simple. If it seems like what you’re doing is far more complicated than it needs to be, it probably is.

C# quick and dirty serialize object to xml string

June 23rd, 2008

csharp.netIf you create an object and have it use the [Serializable] attribute, you can easily serialize it to an xml string using this quick and dirty method. I use it to store the xml as a string in a database field.

Note: Using System.Xml.Serialization namespace

 


public static string SerializeThingToXmlString(object thing)
    {
        try
        {
            StringWriter stringWriter = new StringWriter();
            XmlSerializer serializer = new XmlSerializer(thing.GetType());
            serializer.Serialize(stringWriter, thing);
            return stringWriter.ToString();
        }
        catch (SerializationException)
        {
            return null;
        }
    }