Reputation: 393
I have an xml like this:
<products>
<product>
<name>ad</name>
<category>something</category>
...
<size>S</size>
<color-code>87-3</color-code>
<size-code>24294</size-code>
<size-qty>10</size-qty>
<size-codeproducer>5902228002604</size-codeproducer>
<size>M</size>
<color-code>87-4</color-code>
<size-code>24295</size-code>
<size-qty>64</size-qty>
<size-codeproducer>5902228002611</size-codeproducer>
<size>L</size>
<color-code>87-5</color-code>
<size-code>24296</size-code>
<size-qty>46</size-qty>
<size-codeproducer>5902228002628</size-codeproducer>
<size>XXL</size>
<color-code>87-7</color-code>
<size-code>24298</size-code>
<size-qty>0</size-qty>
<size-codeproducer>5902228002635</size-codeproducer>
</product>
<product>
...
...
...
</product>
</products>
Well I want to separate those repeating nodes of <size>
,<color-code>
and others like:
<product>
<name>ad</name>
<category>something</category>
...
<variation>
<size>S</size>
<color-code>87-3</color-code>
<size-code>24294</size-code>
<size-qty>10</size-qty>
<size-codeproducer>5902228002604</size-codeproducer>
</variation>
<variation>
<size>M</size>
<color-code>87-4</color-code>
<size-code>24295</size-code>
<size-qty>64</size-qty>
<size-codeproducer>5902228002611</size-codeproducer>
</variation>
<variation>
<size>L</size>
<color-code>87-5</color-code>
<size-code>24296</size-code>
<size-qty>46</size-qty>
<size-codeproducer>5902228002628</size-codeproducer>
</variation>
<variation>
<size>XXL</size>
<color-code>87-7</color-code>
<size-code>24298</size-code>
<size-qty>0</size-qty>
<size-codeproducer>5902228002635</size-codeproducer>
</variation>
And I can't really think of a good logic to do that. I'm using php, first thing that I though was using arrays and checking if the node exists, and always checking if the size node exists - if it does to create a new array. Whats the best and easiest approach here?
Upvotes: 0
Views: 106
Reputation: 107577
Consider XSLT, the special-purpose langauge (like SQL) designed to transform XML files such as your specific end-use needs. Like many general-purpose languages, PHP can run XSLT 1.0 as a lower level layer using special libraries (similar to how it runs SQL), namely php-xsl class (requires the .ini extension enabled).
Specifically, the below XSLT rewrites each product node by looping through each size (assuming it will always begin the variation grouping) to retrieve corresponding nodes at the same occurrence.
XSLT (save as .xsl file, a special .xml file)
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="products">
<xsl:copy>
<xsl:apply-templates select="product"/>
</xsl:copy>
</xsl:template>
<xsl:template match="product">
<xsl:copy>
<xsl:variable name="prod_pos" select="position()"/>
<xsl:copy-of select="name|category"/>
<xsl:for-each select="size">
<variation>
<xsl:variable name="size_occur" select="position()"/>
<xsl:copy-of select="."/>
<xsl:copy-of select="/products/product[$prod_pos]/color-code[$size_occur]"/>
<xsl:copy-of select="/products/product[$prod_pos]/size-code[$size_occur]"/>
<xsl:copy-of select="/products/product[$prod_pos]/size-qty[$size_occur]"/>
<xsl:copy-of select="/products/product[$prod_pos]/size-codeproducer[$size_occur]"/>
</variation>
</xsl:for-each>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
PHP
// Load the XML source and XSLT file
$xml = new DOMDocument('1.0', 'UTF-8');
$xml->formatOutput = true;
$xml->preserveWhiteSpace = false;
$xml->load('Input.xml');
$xsl = new DOMDocument;
$xsl->load('XSLTScript.xsl');
// Configure transformer
$proc = new XSLTProcessor;
$proc->importStyleSheet($xsl);
// Transform XML source
$newXML = new DOMDocument;
$newXML = $proc->transformToXML($xml);
echo $newXML;
// Save output to file
$xmlfile = 'Output.xml';
file_put_contents($xmlfile, $newXML);
Output
<products>
<product>
<name>ad</name>
<category>something</category>
<variation>
<size>S</size>
<color-code>87-3</color-code>
<size-code>24294</size-code>
<size-qty>10</size-qty>
<size-codeproducer>5902228002604</size-codeproducer>
</variation>
<variation>
<size>M</size>
<color-code>87-4</color-code>
<size-code>24295</size-code>
<size-qty>64</size-qty>
<size-codeproducer>5902228002611</size-codeproducer>
</variation>
<variation>
<size>L</size>
<color-code>87-5</color-code>
<size-code>24296</size-code>
<size-qty>46</size-qty>
<size-codeproducer>5902228002628</size-codeproducer>
</variation>
<variation>
<size>XXL</size>
<color-code>87-7</color-code>
<size-code>24298</size-code>
<size-qty>0</size-qty>
<size-codeproducer>5902228002635</size-codeproducer>
</variation>
</product>
</products>
Upvotes: 2