Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>An example you can use as a starting point. At least I hope it gives you an idea...</p> <pre><code>&lt;?php define('TYPE_HEADER', 1); define('TYPE_KEY', 2); define('TYPE_DELIMETER', 3); define('TYPE_VALUE', 4); $datafile = 'data.txt'; $fp = fopen($datafile, 'rb') or die('!fopen'); // stores (the first) {header} in 'name' and the root simplexmlelement in 'element' $container = array('name'=&gt;null, 'element'=&gt;null); // stores the name for each item element, the value for the type attribute for subsequent item elements and the simplexmlelement of the current item element $item = array('name'=&gt;null, 'type'=&gt;null, 'current_element'=&gt;null); // the last **key** encountered, used to create new child elements in the current item element when a value is encountered $key = null; while ( false!==($t=getstruct($fp)) ) { switch( $t[0] ) { case TYPE_HEADER: if ( is_null($container['element']) ) { // this is the first time we hit **header - subheader** $container['name'] = $t[1][0]; // ugly hack, &lt; . name . /&gt; $container['element'] = new SimpleXMLElement('&lt;'.$container['name'].'/&gt;'); // each subsequent new item gets the new subheader as type attribute $item['type'] = $t[1][1]; // dummy implementation: "deducting" the item names from header/container[name] $item['name'] = substr($t[1][0], 0, -1); } else { // hitting **header - subheader** the (second, third, nth) time /* header must be the same as the first time (stored in container['name']). Otherwise you need another container element since xml documents can only have one root element */ if ( $container['name'] !== $t[1][0] ) { echo $container['name'], "!==", $t[1][0], "\n"; die('format error'); } else { // subheader may have changed, store it for future item elements $item['type'] = $t[1][1]; } } break; case TYPE_DELIMETER: assert( !is_null($container['element']) ); assert( !is_null($item['name']) ); assert( !is_null($item['type']) ); /* that's maybe not a wise choice. You might want to check the complete item before appending it to the document. But the example is a hack anyway ...so create a new item element and append it to the container right away */ $item['current_element'] = $container['element']-&gt;addChild($item['name']); // set the type-attribute according to the last **header - subheader** encountered $item['current_element']['type'] = $item['type']; break; case TYPE_KEY: $key = $t[1][0]; break; case TYPE_VALUE: assert( !is_null($item['current_element']) ); assert( !is_null($key) ); // this is a value belonging to the "last" key encountered // create a new "key" element with the value as content // and addit to the current item element $tmp = $item['current_element']-&gt;addChild($key, $t[1][0]); break; default: die('unknown token'); } } if ( !is_null($container['element']) ) { $doc = dom_import_simplexml($container['element']); $doc = $doc-&gt;ownerDocument; $doc-&gt;formatOutput = true; echo $doc-&gt;saveXML(); } die; /* Take a look at gettoken() at http://www.tuxradar.com/practicalphp/21/5/6 It breaks the stream into much simpler pieces. In the next step the parser would "combine" or structure the simple tokens into more complex things. This function does both.... @return array(id, array(parameter) */ function getstruct($fp) { if ( feof($fp) ) { return false; } // shortcut: all we care about "happens" on one line // so let php read one line in a single step and then do the pattern matching $line = trim(fgets($fp)); // this matches **key** and **header - subheader** if ( preg_match('#^\*\*([^-]+)(?:-(.*))?\*\*$#', $line, $m) ) { // only for **header - subheader** $m[2] is set. if ( isset($m[2]) ) { return array(TYPE_HEADER, array(trim($m[1]), trim($m[2]))); } else { return array(TYPE_KEY, array($m[1])); } } // this matches _____________ and means "new item" else if ( preg_match('#^_+$#', $line, $m) ) { return array(TYPE_DELIMETER, array()); } // any other non-empty line is a single value else if ( preg_match('#\S#', $line) ) { // you might want to filter the 1),2),3) part out here // could also be two diffrent token types return array(TYPE_VALUE, array($line)); } else { // skip empty lines, would be nicer with tail-recursion... return getstruct($fp); } } </code></pre> <p>prints</p> <pre><code>&lt;?xml version="1.0"?&gt; &lt;FOODS&gt; &lt;FOOD type="TYPE A"&gt; &lt;PRODUCT&gt;1) Mi Pueblito Queso Fresco Authentic Mexican Style Fresh Cheese;&lt;/PRODUCT&gt; &lt;PRODUCT&gt;2) La Fe String Cheese&lt;/PRODUCT&gt; &lt;CODE&gt;Sell by date going back to February 1, 2009&lt;/CODE&gt; &lt;MANUFACTURER&gt;Quesos Mi Pueblito, LLC, Passaic, NJ.&lt;/MANUFACTURER&gt; &lt;VOLUME OF UNITS&gt;11,000 boxes&lt;/VOLUME OF UNITS&gt; &lt;DISTRIBUTION&gt;NJ, NY, DE, MD, CT, VA&lt;/DISTRIBUTION&gt; &lt;/FOOD&gt; &lt;FOOD type="TYPE A"&gt; &lt;PRODUCT&gt;1) Peanut Brittle No Sugar Added;&lt;/PRODUCT&gt; &lt;PRODUCT&gt;2) Peanut Brittle Small Grind;&lt;/PRODUCT&gt; &lt;PRODUCT&gt;3) Homestyle Peanut Brittle Nuggets/Coconut Oil Coating&lt;/PRODUCT&gt; &lt;CODE&gt;1) Lots 7109 - 8350 inclusive;&lt;/CODE&gt; &lt;CODE&gt;2) Lots 8198 - 8330 inclusive;&lt;/CODE&gt; &lt;CODE&gt;3) Lots 7075 - 9012 inclusive;&lt;/CODE&gt; &lt;CODE&gt;4) Lots 7100 - 8057 inclusive;&lt;/CODE&gt; &lt;CODE&gt;5) Lots 7152 - 8364 inclusive&lt;/CODE&gt; &lt;MANUFACTURER&gt;Star Kay White, Inc., Congers, NY.&lt;/MANUFACTURER&gt; &lt;VOLUME OF UNITS&gt;5,749 units&lt;/VOLUME OF UNITS&gt; &lt;DISTRIBUTION&gt;NY, NJ, MA, PA, OH, FL, TX, UT, CA, IA, NV, MO and IN&lt;/DISTRIBUTION&gt; &lt;/FOOD&gt; &lt;FOOD type="TYPE B"&gt; &lt;PRODUCT&gt;Cool River Bebidas Naturales - West Indian Cherry Fruit Acerola 16% Juice;&lt;/PRODUCT&gt; &lt;CODE&gt;990-10/2 10/5&lt;/CODE&gt; &lt;MANUFACTURER&gt;San Mar Manufacturing Corp., Catano, PR.&lt;/MANUFACTURER&gt; &lt;VOLUME OF UNITS&gt;384&lt;/VOLUME OF UNITS&gt; &lt;DISTRIBUTION&gt;PR&lt;/DISTRIBUTION&gt; &lt;/FOOD&gt; &lt;/FOODS&gt; </code></pre> <p>Unfortunately the status of the php module for <a href="http://www.antlr.org/" rel="nofollow noreferrer">ANTLR</a> currently is "<a href="http://www.antlr.org/wiki/display/ANTLR3/Code+Generation+Targets" rel="nofollow noreferrer">Runtime is in alpha status.</a>" but it might be worth a try anyway...</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload