btg_1967
btg_1967

Reputation: 79

How do I transform nested XML into simple XML

Firstly, I've been scanning for an answer to this one for days, to no avail - but self teaching myself after dealing with years of raw .net has a few challenges, so sorry if this is a really basic issue.

Two questions:

  1. XSLT or manual looping, or
  2. what am I missing...?

I'm trying to convert the 'Items' element of a nested XML doc without any additional libraries:

example.xml:

<?xml version="1.0" encoding="utf-8"?>
<Order>
  <stuff></stuff>
  <Items>
    <OrderItem>
      <qty>1</qty>
      <Name>Latte</Name>
      <Cost>$  4.50</Cost>
      <Options ID="1">
        <Cost>0.50</Cost>
        <Name>Soy Milk</Name>
        <QTY>1</QTY>
      </Options>
      <Options ID="2">
        <Cost>0.00</Cost>
        <Name>Sugar</Name>
        <QTY>2</QTY>
      </Options>
    </OrderItem>
  </Items>
  <MoreStuff></MoreStuff>
</Order>

into a flat version with some text indenting

^^^ preceding text bits ^^^   
<line>    1   Latte                   $4.50 </line>
<line>           1 x Soy Milk (0.50)        </line>
<line>           2 x Sugar    (0.00)        </line>
---- continue for other bits ---

I'm certain I'm missing something, as this should be really easy, but I',m haveing a devil of a time getting this to work:

$xml = simplexml_load_file('<<source file>>');
foreach($xml->Items->children() as $child)
  {
    echo '<text> ' . $child->qty . '  ' . $child->Name . '    ' . $child->Cost . '</text>';
  }

So I'm pretty certain I'm falling into a really simple newb error.

Upvotes: 0

Views: 152

Answers (1)

hek2mgl
hek2mgl

Reputation: 158020

I would use XSLT for that. Having the following stylesheet:

flatten.xsl

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/">
        <xsl:for-each select="/Order/Items/OrderItem">
        <line>
            <xsl:text>    </xsl:text>
            <xsl:value-of select="qty" />
            <xsl:text>   </xsl:text>
            <xsl:value-of select="Name" />
            <xsl:text>   </xsl:text>
            <xsl:value-of select="Cost" />
            <xsl:text>   </xsl:text>
        </line>
            <xsl:for-each select="Options"><xsl:text>
</xsl:text>
        <line>
            <xsl:text>       </xsl:text>
            <xsl:value-of select="QTY" />
            <xsl:text> x </xsl:text>
            <xsl:value-of select="Name" />
            <xsl:text>   </xsl:text>
            <xsl:value-of select="Cost" />
            <xsl:text>   </xsl:text>
        </line>
            </xsl:for-each>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

You can apply the above stylesheet using the following code in PHP:

$xml = new DOMDocument();
$xsl = new DOMDocument();

$xml->load("example.xml");
$xsl->load("flatten.xsl");

$xsltproc  = new XSLTProcessor();
$xsltproc->importStyleSheet($xsl);

echo $xsltproc->transformToXML($xml);

which outputs:

<?xml version="1.0"?>
<line>    1   Latte   $  4.50   </line>
<line>       1 x Soy Milk   0.50   </line>
<line>       2 x Sugar   0.00   </line>

Upvotes: 1

Related Questions