найти блок xml и заменить все, регулярное выражение, чтобы соответствовать и перезвонить, чтобы перезаписать

Мне нужно просто выполнить быстрое совпадение и заменить все, что исходит от xml. Я не хочу фраза файла, так как файл похож на 100mb, и я не могу остановить это. Итак, вот пример данных.

<?xml version="1.0" encoding="UTF-8"?> <products> <product active="1" on_sale="0" discountable="0"> <sku>SKUTARGET</sku> <name><![CDATA[sdfsdf (NET)]]></name> <description><![CDATA[agag adgsgsdg asdgsdg]]></description> <keywords></keywords> <price>9.000000</price> <stock_quantity>35</stock_quantity> <reorder_quantity>0</reorder_quantity> <height>0.000000</height> <length>0.000000</length> <diameter>0.000000</diameter> <weight>0.000000</weight> <color>Black</color> <material>PVC</material> <barcode>883045010070</barcode> <release_date>2008-11-10</release_date> <images> <image>/sdssd/sdfsd.jpg</image> <image>/AL10sdfsds07XO/sdfsd.jpg</image> </images> <categories> <category code="166" video="0" parent="172">sd &amp; Sexy sdf</category> <category code="172" video="0" parent="">sd &amp; dddsdsds</category> <category code="641" video="0" parent="172">sdfsdf Costume sdfsdfsdf</category> </categories> <manufacturer code="AL" video="0">sdfsdf sdfs</manufacturer> <type code="LI" video="0">sdfsd</type> </product> <product active="1" on_sale="0" discountable="0"> <sku>XXXXXXX</sku> <name><![CDATA[LEATHER sdfsdf (NET)]]></name> <description><![CDATA[asdgsdgsd sad sadg asdg asdg asdg asdg asdg asdg asdg asdg asdg asdg asdg]]></description> <keywords></keywords> <price>5.000000</price> <stock_quantity>36</stock_quantity> <reorder_quantity>0</reorder_quantity> <height>0.000000</height> <length>0.000000</length> <diameter>0.000000</diameter> <weight>0.000000</weight> <color>Black</color> <material>Leather</material> <barcode>883045300164</barcode> <release_date>2008-11-10</release_date> <images> <image>/AL10sds0XO/sdsdsd.jpg</image> <image>/sdsds/AL1sd00XOB.jpg</image> <image>/AL1sdsds00XO/sdsds.jpg</image> </images> <categories> <category code="80" video="0" parent="44">sdgsdgsdg</category> <category code="181" video="0" parent="172">Sleep &amp; Lounge</category> </categories> <manufacturer code="AL" video="0">Allure sdsds</manufacturer> <type code="LI" video="0">sdsfsdfsd</type> </product> </products> 

Мне нужен только один блок, начиная с продуктов узла, где sku является var в этом случае «SKUTARGET»

  <product active="1" on_sale="0" discountable="0"> <sku>SKUTARGET</sku> <name><![CDATA[sdfsdf (NET)]]></name> <description><![CDATA[agag adgsgsdg asdgsdg]]></description> <keywords></keywords> <price>9.000000</price> <stock_quantity>35</stock_quantity> <reorder_quantity>0</reorder_quantity> <height>0.000000</height> <length>0.000000</length> <diameter>0.000000</diameter> <weight>0.000000</weight> <color>Black</color> <material>PVC</material> <barcode>883045010070</barcode> <release_date>2008-11-10</release_date> <images> <image>/sdssd/sdfsd.jpg</image> <image>/AL10sdfsds07XO/sdfsd.jpg</image> </images> <categories> <category code="166" video="0" parent="172">sd &amp; Sexy sdf</category> <category code="172" video="0" parent="">sd &amp; dddsdsds</category> <category code="641" video="0" parent="172">sdfsdf Costume sdfsdfsdf</category> </categories> <manufacturer code="AL" video="0">sdfsdf sdfs</manufacturer> <type code="LI" video="0">sdfsd</type> </product> -  <product active="1" on_sale="0" discountable="0"> <sku>SKUTARGET</sku> <name><![CDATA[sdfsdf (NET)]]></name> <description><![CDATA[agag adgsgsdg asdgsdg]]></description> <keywords></keywords> <price>9.000000</price> <stock_quantity>35</stock_quantity> <reorder_quantity>0</reorder_quantity> <height>0.000000</height> <length>0.000000</length> <diameter>0.000000</diameter> <weight>0.000000</weight> <color>Black</color> <material>PVC</material> <barcode>883045010070</barcode> <release_date>2008-11-10</release_date> <images> <image>/sdssd/sdfsd.jpg</image> <image>/AL10sdfsds07XO/sdfsd.jpg</image> </images> <categories> <category code="166" video="0" parent="172">sd &amp; Sexy sdf</category> <category code="172" video="0" parent="">sd &amp; dddsdsds</category> <category code="641" video="0" parent="172">sdfsdf Costume sdfsdfsdf</category> </categories> <manufacturer code="AL" video="0">sdfsdf sdfs</manufacturer> <type code="LI" video="0">sdfsd</type> </product> -  <product active="1" on_sale="0" discountable="0"> <sku>SKUTARGET</sku> <name><![CDATA[sdfsdf (NET)]]></name> <description><![CDATA[agag adgsgsdg asdgsdg]]></description> <keywords></keywords> <price>9.000000</price> <stock_quantity>35</stock_quantity> <reorder_quantity>0</reorder_quantity> <height>0.000000</height> <length>0.000000</length> <diameter>0.000000</diameter> <weight>0.000000</weight> <color>Black</color> <material>PVC</material> <barcode>883045010070</barcode> <release_date>2008-11-10</release_date> <images> <image>/sdssd/sdfsd.jpg</image> <image>/AL10sdfsds07XO/sdfsd.jpg</image> </images> <categories> <category code="166" video="0" parent="172">sd &amp; Sexy sdf</category> <category code="172" video="0" parent="">sd &amp; dddsdsds</category> <category code="641" video="0" parent="172">sdfsdf Costume sdfsdfsdf</category> </categories> <manufacturer code="AL" video="0">sdfsdf sdfs</manufacturer> <type code="LI" video="0">sdfsd</type> </product> 

Вот код, с которым я сейчас работаю

  <?php ob_start(); ?> <?xml version="1.0" encoding="UTF-8"?> <products> <product active="1" on_sale="0" discountable="0"> <sku>SKUTARGET</sku> <name><![CDATA[sdfsdf (NET)]]></name> <description><![CDATA[agag adgsgsdg asdgsdg]]></description> <keywords></keywords> <price>9.000000</price> <stock_quantity>35</stock_quantity> <reorder_quantity>0</reorder_quantity> <height>0.000000</height> <length>0.000000</length> <diameter>0.000000</diameter> <weight>0.000000</weight> <color>Black</color> <material>PVC</material> <barcode>883045010070</barcode> <release_date>2008-11-10</release_date> <images> <image>/sdssd/sdfsd.jpg</image> <image>/AL10sdfsds07XO/sdfsd.jpg</image> </images> <categories> <category code="166" video="0" parent="172">sd &amp; Sexy sdf</category> <category code="172" video="0" parent="">sd &amp; dddsdsds</category> <category code="641" video="0" parent="172">sdfsdf Costume sdfsdfsdf</category> </categories> <manufacturer code="AL" video="0">sdfsdf sdfs</manufacturer> <type code="LI" video="0">sdfsd</type> </product> <product active="1" on_sale="0" discountable="0"> <sku>XXXXXXX</sku> <name><![CDATA[LEATHER sdfsdf (NET)]]></name> <description><![CDATA[asdgsdgsd sad sadg asdg asdg asdg asdg asdg asdg asdg asdg asdg asdg asdg]]></description> <keywords></keywords> <price>5.000000</price> <stock_quantity>36</stock_quantity> <reorder_quantity>0</reorder_quantity> <height>0.000000</height> <length>0.000000</length> <diameter>0.000000</diameter> <weight>0.000000</weight> <color>Black</color> <material>Leather</material> <barcode>883045300164</barcode> <release_date>2008-11-10</release_date> <images> <image>/AL10sds0XO/sdsdsd.jpg</image> <image>/sdsds/AL1sd00XOB.jpg</image> <image>/AL1sdsds00XO/sdsds.jpg</image> </images> <categories> <category code="80" video="0" parent="44">sdgsdgsdg</category> <category code="181" video="0" parent="172">Sleep &amp; Lounge</category> </categories> <manufacturer code="AL" video="0">Allure sdsds</manufacturer> <type code="LI" video="0">sdsfsdfsd</type> </product> </products> <?php $xml_str = ob_get_contents(); ob_end_clean(); $tar_sku="SKUTARGET"; // this is the sku of the product block I need to have $pat= '/^.*(<product *<sku>'.$tar_sku.'</sku>*</product>).*$/is'; // this should match the block with the sku but no other block $replacement='$1';//This should overwrite everything with that found block. $returnValue = preg_replace($pat, $replacement, $xml_str); -  <?php ob_start(); ?> <?xml version="1.0" encoding="UTF-8"?> <products> <product active="1" on_sale="0" discountable="0"> <sku>SKUTARGET</sku> <name><![CDATA[sdfsdf (NET)]]></name> <description><![CDATA[agag adgsgsdg asdgsdg]]></description> <keywords></keywords> <price>9.000000</price> <stock_quantity>35</stock_quantity> <reorder_quantity>0</reorder_quantity> <height>0.000000</height> <length>0.000000</length> <diameter>0.000000</diameter> <weight>0.000000</weight> <color>Black</color> <material>PVC</material> <barcode>883045010070</barcode> <release_date>2008-11-10</release_date> <images> <image>/sdssd/sdfsd.jpg</image> <image>/AL10sdfsds07XO/sdfsd.jpg</image> </images> <categories> <category code="166" video="0" parent="172">sd &amp; Sexy sdf</category> <category code="172" video="0" parent="">sd &amp; dddsdsds</category> <category code="641" video="0" parent="172">sdfsdf Costume sdfsdfsdf</category> </categories> <manufacturer code="AL" video="0">sdfsdf sdfs</manufacturer> <type code="LI" video="0">sdfsd</type> </product> <product active="1" on_sale="0" discountable="0"> <sku>XXXXXXX</sku> <name><![CDATA[LEATHER sdfsdf (NET)]]></name> <description><![CDATA[asdgsdgsd sad sadg asdg asdg asdg asdg asdg asdg asdg asdg asdg asdg asdg]]></description> <keywords></keywords> <price>5.000000</price> <stock_quantity>36</stock_quantity> <reorder_quantity>0</reorder_quantity> <height>0.000000</height> <length>0.000000</length> <diameter>0.000000</diameter> <weight>0.000000</weight> <color>Black</color> <material>Leather</material> <barcode>883045300164</barcode> <release_date>2008-11-10</release_date> <images> <image>/AL10sds0XO/sdsdsd.jpg</image> <image>/sdsds/AL1sd00XOB.jpg</image> <image>/AL1sdsds00XO/sdsds.jpg</image> </images> <categories> <category code="80" video="0" parent="44">sdgsdgsdg</category> <category code="181" video="0" parent="172">Sleep &amp; Lounge</category> </categories> <manufacturer code="AL" video="0">Allure sdsds</manufacturer> <type code="LI" video="0">sdsfsdfsd</type> </product> </products> <?php $xml_str = ob_get_contents(); ob_end_clean(); $tar_sku="SKUTARGET"; // this is the sku of the product block I need to have $pat= '/^.*(<product *<sku>'.$tar_sku.'</sku>*</product>).*$/is'; // this should match the block with the sku but no other block $replacement='$1';//This should overwrite everything with that found block. $returnValue = preg_replace($pat, $replacement, $xml_str); -  <?php ob_start(); ?> <?xml version="1.0" encoding="UTF-8"?> <products> <product active="1" on_sale="0" discountable="0"> <sku>SKUTARGET</sku> <name><![CDATA[sdfsdf (NET)]]></name> <description><![CDATA[agag adgsgsdg asdgsdg]]></description> <keywords></keywords> <price>9.000000</price> <stock_quantity>35</stock_quantity> <reorder_quantity>0</reorder_quantity> <height>0.000000</height> <length>0.000000</length> <diameter>0.000000</diameter> <weight>0.000000</weight> <color>Black</color> <material>PVC</material> <barcode>883045010070</barcode> <release_date>2008-11-10</release_date> <images> <image>/sdssd/sdfsd.jpg</image> <image>/AL10sdfsds07XO/sdfsd.jpg</image> </images> <categories> <category code="166" video="0" parent="172">sd &amp; Sexy sdf</category> <category code="172" video="0" parent="">sd &amp; dddsdsds</category> <category code="641" video="0" parent="172">sdfsdf Costume sdfsdfsdf</category> </categories> <manufacturer code="AL" video="0">sdfsdf sdfs</manufacturer> <type code="LI" video="0">sdfsd</type> </product> <product active="1" on_sale="0" discountable="0"> <sku>XXXXXXX</sku> <name><![CDATA[LEATHER sdfsdf (NET)]]></name> <description><![CDATA[asdgsdgsd sad sadg asdg asdg asdg asdg asdg asdg asdg asdg asdg asdg asdg]]></description> <keywords></keywords> <price>5.000000</price> <stock_quantity>36</stock_quantity> <reorder_quantity>0</reorder_quantity> <height>0.000000</height> <length>0.000000</length> <diameter>0.000000</diameter> <weight>0.000000</weight> <color>Black</color> <material>Leather</material> <barcode>883045300164</barcode> <release_date>2008-11-10</release_date> <images> <image>/AL10sds0XO/sdsdsd.jpg</image> <image>/sdsds/AL1sd00XOB.jpg</image> <image>/AL1sdsds00XO/sdsds.jpg</image> </images> <categories> <category code="80" video="0" parent="44">sdgsdgsdg</category> <category code="181" video="0" parent="172">Sleep &amp; Lounge</category> </categories> <manufacturer code="AL" video="0">Allure sdsds</manufacturer> <type code="LI" video="0">sdsfsdfsd</type> </product> </products> <?php $xml_str = ob_get_contents(); ob_end_clean(); $tar_sku="SKUTARGET"; // this is the sku of the product block I need to have $pat= '/^.*(<product *<sku>'.$tar_sku.'</sku>*</product>).*$/is'; // this should match the block with the sku but no other block $replacement='$1';//This should overwrite everything with that found block. $returnValue = preg_replace($pat, $replacement, $xml_str); -  <?php ob_start(); ?> <?xml version="1.0" encoding="UTF-8"?> <products> <product active="1" on_sale="0" discountable="0"> <sku>SKUTARGET</sku> <name><![CDATA[sdfsdf (NET)]]></name> <description><![CDATA[agag adgsgsdg asdgsdg]]></description> <keywords></keywords> <price>9.000000</price> <stock_quantity>35</stock_quantity> <reorder_quantity>0</reorder_quantity> <height>0.000000</height> <length>0.000000</length> <diameter>0.000000</diameter> <weight>0.000000</weight> <color>Black</color> <material>PVC</material> <barcode>883045010070</barcode> <release_date>2008-11-10</release_date> <images> <image>/sdssd/sdfsd.jpg</image> <image>/AL10sdfsds07XO/sdfsd.jpg</image> </images> <categories> <category code="166" video="0" parent="172">sd &amp; Sexy sdf</category> <category code="172" video="0" parent="">sd &amp; dddsdsds</category> <category code="641" video="0" parent="172">sdfsdf Costume sdfsdfsdf</category> </categories> <manufacturer code="AL" video="0">sdfsdf sdfs</manufacturer> <type code="LI" video="0">sdfsd</type> </product> <product active="1" on_sale="0" discountable="0"> <sku>XXXXXXX</sku> <name><![CDATA[LEATHER sdfsdf (NET)]]></name> <description><![CDATA[asdgsdgsd sad sadg asdg asdg asdg asdg asdg asdg asdg asdg asdg asdg asdg]]></description> <keywords></keywords> <price>5.000000</price> <stock_quantity>36</stock_quantity> <reorder_quantity>0</reorder_quantity> <height>0.000000</height> <length>0.000000</length> <diameter>0.000000</diameter> <weight>0.000000</weight> <color>Black</color> <material>Leather</material> <barcode>883045300164</barcode> <release_date>2008-11-10</release_date> <images> <image>/AL10sds0XO/sdsdsd.jpg</image> <image>/sdsds/AL1sd00XOB.jpg</image> <image>/AL1sdsds00XO/sdsds.jpg</image> </images> <categories> <category code="80" video="0" parent="44">sdgsdgsdg</category> <category code="181" video="0" parent="172">Sleep &amp; Lounge</category> </categories> <manufacturer code="AL" video="0">Allure sdsds</manufacturer> <type code="LI" video="0">sdsfsdfsd</type> </product> </products> <?php $xml_str = ob_get_contents(); ob_end_clean(); $tar_sku="SKUTARGET"; // this is the sku of the product block I need to have $pat= '/^.*(<product *<sku>'.$tar_sku.'</sku>*</product>).*$/is'; // this should match the block with the sku but no other block $replacement='$1';//This should overwrite everything with that found block. $returnValue = preg_replace($pat, $replacement, $xml_str); -  <?php ob_start(); ?> <?xml version="1.0" encoding="UTF-8"?> <products> <product active="1" on_sale="0" discountable="0"> <sku>SKUTARGET</sku> <name><![CDATA[sdfsdf (NET)]]></name> <description><![CDATA[agag adgsgsdg asdgsdg]]></description> <keywords></keywords> <price>9.000000</price> <stock_quantity>35</stock_quantity> <reorder_quantity>0</reorder_quantity> <height>0.000000</height> <length>0.000000</length> <diameter>0.000000</diameter> <weight>0.000000</weight> <color>Black</color> <material>PVC</material> <barcode>883045010070</barcode> <release_date>2008-11-10</release_date> <images> <image>/sdssd/sdfsd.jpg</image> <image>/AL10sdfsds07XO/sdfsd.jpg</image> </images> <categories> <category code="166" video="0" parent="172">sd &amp; Sexy sdf</category> <category code="172" video="0" parent="">sd &amp; dddsdsds</category> <category code="641" video="0" parent="172">sdfsdf Costume sdfsdfsdf</category> </categories> <manufacturer code="AL" video="0">sdfsdf sdfs</manufacturer> <type code="LI" video="0">sdfsd</type> </product> <product active="1" on_sale="0" discountable="0"> <sku>XXXXXXX</sku> <name><![CDATA[LEATHER sdfsdf (NET)]]></name> <description><![CDATA[asdgsdgsd sad sadg asdg asdg asdg asdg asdg asdg asdg asdg asdg asdg asdg]]></description> <keywords></keywords> <price>5.000000</price> <stock_quantity>36</stock_quantity> <reorder_quantity>0</reorder_quantity> <height>0.000000</height> <length>0.000000</length> <diameter>0.000000</diameter> <weight>0.000000</weight> <color>Black</color> <material>Leather</material> <barcode>883045300164</barcode> <release_date>2008-11-10</release_date> <images> <image>/AL10sds0XO/sdsdsd.jpg</image> <image>/sdsds/AL1sd00XOB.jpg</image> <image>/AL1sdsds00XO/sdsds.jpg</image> </images> <categories> <category code="80" video="0" parent="44">sdgsdgsdg</category> <category code="181" video="0" parent="172">Sleep &amp; Lounge</category> </categories> <manufacturer code="AL" video="0">Allure sdsds</manufacturer> <type code="LI" video="0">sdsfsdfsd</type> </product> </products> <?php $xml_str = ob_get_contents(); ob_end_clean(); $tar_sku="SKUTARGET"; // this is the sku of the product block I need to have $pat= '/^.*(<product *<sku>'.$tar_sku.'</sku>*</product>).*$/is'; // this should match the block with the sku but no other block $replacement='$1';//This should overwrite everything with that found block. $returnValue = preg_replace($pat, $replacement, $xml_str); 

Любая помощь будет большой. Благодарю. Джереми

[редактировать]

Вот тестовый код из приведенного ниже предложения. Пока еще не работает. Я ожидал, чтобы повторить эту строку блока xml с этим соглашением sku. пока не повезло.

  <?php error_reporting(E_ALL); ini_set('display_errors', '1'); umask(0); $xml_str = <<<EOD <?xml version="1.0" encoding="UTF-8"?> <products> <product active="1" on_sale="0" discountable="0"> <sku>SKUTARGET</sku> <name><![CDATA[sdfsdf (NET)]]></name> <description><![CDATA[agag adgsgsdg asdgsdg]]></description> <keywords></keywords> <price>9.000000</price> <stock_quantity>35</stock_quantity> <reorder_quantity>0</reorder_quantity> <height>0.000000</height> <length>0.000000</length> <diameter>0.000000</diameter> <weight>0.000000</weight> <color>Black</color> <material>PVC</material> <barcode>883045010070</barcode> <release_date>2008-11-10</release_date> <images> <image>/sdssd/sdfsd.jpg</image> <image>/AL10sdfsds07XO/sdfsd.jpg</image> </images> <categories> <category code="166" video="0" parent="172">sd &amp; Sexy sdf</category> <category code="172" video="0" parent="">sd &amp; dddsdsds</category> <category code="641" video="0" parent="172">sdfsdf Costume sdfsdfsdf</category> </categories> <manufacturer code="AL" video="0">sdfsdf sdfs</manufacturer> <type code="LI" video="0">sdfsd</type> </product> <product active="1" on_sale="0" discountable="0"> <sku>XXXXXXX</sku> <name><![CDATA[LEATHER sdfsdf (NET)]]></name> <description><![CDATA[asdgsdgsd sad sadg asdg asdg asdg asdg asdg asdg asdg asdg asdg asdg asdg]]></description> <keywords></keywords> <price>5.000000</price> <stock_quantity>36</stock_quantity> <reorder_quantity>0</reorder_quantity> <height>0.000000</height> <length>0.000000</length> <diameter>0.000000</diameter> <weight>0.000000</weight> <color>Black</color> <material>Leather</material> <barcode>883045300164</barcode> <release_date>2008-11-10</release_date> <images> <image>/AL10sds0XO/sdsdsd.jpg</image> <image>/sdsds/AL1sd00XOB.jpg</image> <image>/AL1sdsds00XO/sdsds.jpg</image> </images> <categories> <category code="80" video="0" parent="44">sdgsdgsdg</category> <category code="181" video="0" parent="172">Sleep &amp; Lounge</category> </categories> <manufacturer code="AL" video="0">Allure sdsds</manufacturer> <type code="LI" video="0">sdsfsdfsd</type> </product> </products> EOD; $tar_sku="SKUTARGET"; // this is the sku of the product block I need to have $pattern = "~<product .*?<sku>$tar_sku</sku>.*?</product>~is"; $returnValue = preg_match($pattern,$xml_str); echo '--'.$returnValue[0]; -  <?php error_reporting(E_ALL); ini_set('display_errors', '1'); umask(0); $xml_str = <<<EOD <?xml version="1.0" encoding="UTF-8"?> <products> <product active="1" on_sale="0" discountable="0"> <sku>SKUTARGET</sku> <name><![CDATA[sdfsdf (NET)]]></name> <description><![CDATA[agag adgsgsdg asdgsdg]]></description> <keywords></keywords> <price>9.000000</price> <stock_quantity>35</stock_quantity> <reorder_quantity>0</reorder_quantity> <height>0.000000</height> <length>0.000000</length> <diameter>0.000000</diameter> <weight>0.000000</weight> <color>Black</color> <material>PVC</material> <barcode>883045010070</barcode> <release_date>2008-11-10</release_date> <images> <image>/sdssd/sdfsd.jpg</image> <image>/AL10sdfsds07XO/sdfsd.jpg</image> </images> <categories> <category code="166" video="0" parent="172">sd &amp; Sexy sdf</category> <category code="172" video="0" parent="">sd &amp; dddsdsds</category> <category code="641" video="0" parent="172">sdfsdf Costume sdfsdfsdf</category> </categories> <manufacturer code="AL" video="0">sdfsdf sdfs</manufacturer> <type code="LI" video="0">sdfsd</type> </product> <product active="1" on_sale="0" discountable="0"> <sku>XXXXXXX</sku> <name><![CDATA[LEATHER sdfsdf (NET)]]></name> <description><![CDATA[asdgsdgsd sad sadg asdg asdg asdg asdg asdg asdg asdg asdg asdg asdg asdg]]></description> <keywords></keywords> <price>5.000000</price> <stock_quantity>36</stock_quantity> <reorder_quantity>0</reorder_quantity> <height>0.000000</height> <length>0.000000</length> <diameter>0.000000</diameter> <weight>0.000000</weight> <color>Black</color> <material>Leather</material> <barcode>883045300164</barcode> <release_date>2008-11-10</release_date> <images> <image>/AL10sds0XO/sdsdsd.jpg</image> <image>/sdsds/AL1sd00XOB.jpg</image> <image>/AL1sdsds00XO/sdsds.jpg</image> </images> <categories> <category code="80" video="0" parent="44">sdgsdgsdg</category> <category code="181" video="0" parent="172">Sleep &amp; Lounge</category> </categories> <manufacturer code="AL" video="0">Allure sdsds</manufacturer> <type code="LI" video="0">sdsfsdfsd</type> </product> </products> EOD; $tar_sku="SKUTARGET"; // this is the sku of the product block I need to have $pattern = "~<product .*?<sku>$tar_sku</sku>.*?</product>~is"; $returnValue = preg_match($pattern,$xml_str); echo '--'.$returnValue[0]; -  <?php error_reporting(E_ALL); ini_set('display_errors', '1'); umask(0); $xml_str = <<<EOD <?xml version="1.0" encoding="UTF-8"?> <products> <product active="1" on_sale="0" discountable="0"> <sku>SKUTARGET</sku> <name><![CDATA[sdfsdf (NET)]]></name> <description><![CDATA[agag adgsgsdg asdgsdg]]></description> <keywords></keywords> <price>9.000000</price> <stock_quantity>35</stock_quantity> <reorder_quantity>0</reorder_quantity> <height>0.000000</height> <length>0.000000</length> <diameter>0.000000</diameter> <weight>0.000000</weight> <color>Black</color> <material>PVC</material> <barcode>883045010070</barcode> <release_date>2008-11-10</release_date> <images> <image>/sdssd/sdfsd.jpg</image> <image>/AL10sdfsds07XO/sdfsd.jpg</image> </images> <categories> <category code="166" video="0" parent="172">sd &amp; Sexy sdf</category> <category code="172" video="0" parent="">sd &amp; dddsdsds</category> <category code="641" video="0" parent="172">sdfsdf Costume sdfsdfsdf</category> </categories> <manufacturer code="AL" video="0">sdfsdf sdfs</manufacturer> <type code="LI" video="0">sdfsd</type> </product> <product active="1" on_sale="0" discountable="0"> <sku>XXXXXXX</sku> <name><![CDATA[LEATHER sdfsdf (NET)]]></name> <description><![CDATA[asdgsdgsd sad sadg asdg asdg asdg asdg asdg asdg asdg asdg asdg asdg asdg]]></description> <keywords></keywords> <price>5.000000</price> <stock_quantity>36</stock_quantity> <reorder_quantity>0</reorder_quantity> <height>0.000000</height> <length>0.000000</length> <diameter>0.000000</diameter> <weight>0.000000</weight> <color>Black</color> <material>Leather</material> <barcode>883045300164</barcode> <release_date>2008-11-10</release_date> <images> <image>/AL10sds0XO/sdsdsd.jpg</image> <image>/sdsds/AL1sd00XOB.jpg</image> <image>/AL1sdsds00XO/sdsds.jpg</image> </images> <categories> <category code="80" video="0" parent="44">sdgsdgsdg</category> <category code="181" video="0" parent="172">Sleep &amp; Lounge</category> </categories> <manufacturer code="AL" video="0">Allure sdsds</manufacturer> <type code="LI" video="0">sdsfsdfsd</type> </product> </products> EOD; $tar_sku="SKUTARGET"; // this is the sku of the product block I need to have $pattern = "~<product .*?<sku>$tar_sku</sku>.*?</product>~is"; $returnValue = preg_match($pattern,$xml_str); echo '--'.$returnValue[0]; -  <?php error_reporting(E_ALL); ini_set('display_errors', '1'); umask(0); $xml_str = <<<EOD <?xml version="1.0" encoding="UTF-8"?> <products> <product active="1" on_sale="0" discountable="0"> <sku>SKUTARGET</sku> <name><![CDATA[sdfsdf (NET)]]></name> <description><![CDATA[agag adgsgsdg asdgsdg]]></description> <keywords></keywords> <price>9.000000</price> <stock_quantity>35</stock_quantity> <reorder_quantity>0</reorder_quantity> <height>0.000000</height> <length>0.000000</length> <diameter>0.000000</diameter> <weight>0.000000</weight> <color>Black</color> <material>PVC</material> <barcode>883045010070</barcode> <release_date>2008-11-10</release_date> <images> <image>/sdssd/sdfsd.jpg</image> <image>/AL10sdfsds07XO/sdfsd.jpg</image> </images> <categories> <category code="166" video="0" parent="172">sd &amp; Sexy sdf</category> <category code="172" video="0" parent="">sd &amp; dddsdsds</category> <category code="641" video="0" parent="172">sdfsdf Costume sdfsdfsdf</category> </categories> <manufacturer code="AL" video="0">sdfsdf sdfs</manufacturer> <type code="LI" video="0">sdfsd</type> </product> <product active="1" on_sale="0" discountable="0"> <sku>XXXXXXX</sku> <name><![CDATA[LEATHER sdfsdf (NET)]]></name> <description><![CDATA[asdgsdgsd sad sadg asdg asdg asdg asdg asdg asdg asdg asdg asdg asdg asdg]]></description> <keywords></keywords> <price>5.000000</price> <stock_quantity>36</stock_quantity> <reorder_quantity>0</reorder_quantity> <height>0.000000</height> <length>0.000000</length> <diameter>0.000000</diameter> <weight>0.000000</weight> <color>Black</color> <material>Leather</material> <barcode>883045300164</barcode> <release_date>2008-11-10</release_date> <images> <image>/AL10sds0XO/sdsdsd.jpg</image> <image>/sdsds/AL1sd00XOB.jpg</image> <image>/AL1sdsds00XO/sdsds.jpg</image> </images> <categories> <category code="80" video="0" parent="44">sdgsdgsdg</category> <category code="181" video="0" parent="172">Sleep &amp; Lounge</category> </categories> <manufacturer code="AL" video="0">Allure sdsds</manufacturer> <type code="LI" video="0">sdsfsdfsd</type> </product> </products> EOD; $tar_sku="SKUTARGET"; // this is the sku of the product block I need to have $pattern = "~<product .*?<sku>$tar_sku</sku>.*?</product>~is"; $returnValue = preg_match($pattern,$xml_str); echo '--'.$returnValue[0]; -  <?php error_reporting(E_ALL); ini_set('display_errors', '1'); umask(0); $xml_str = <<<EOD <?xml version="1.0" encoding="UTF-8"?> <products> <product active="1" on_sale="0" discountable="0"> <sku>SKUTARGET</sku> <name><![CDATA[sdfsdf (NET)]]></name> <description><![CDATA[agag adgsgsdg asdgsdg]]></description> <keywords></keywords> <price>9.000000</price> <stock_quantity>35</stock_quantity> <reorder_quantity>0</reorder_quantity> <height>0.000000</height> <length>0.000000</length> <diameter>0.000000</diameter> <weight>0.000000</weight> <color>Black</color> <material>PVC</material> <barcode>883045010070</barcode> <release_date>2008-11-10</release_date> <images> <image>/sdssd/sdfsd.jpg</image> <image>/AL10sdfsds07XO/sdfsd.jpg</image> </images> <categories> <category code="166" video="0" parent="172">sd &amp; Sexy sdf</category> <category code="172" video="0" parent="">sd &amp; dddsdsds</category> <category code="641" video="0" parent="172">sdfsdf Costume sdfsdfsdf</category> </categories> <manufacturer code="AL" video="0">sdfsdf sdfs</manufacturer> <type code="LI" video="0">sdfsd</type> </product> <product active="1" on_sale="0" discountable="0"> <sku>XXXXXXX</sku> <name><![CDATA[LEATHER sdfsdf (NET)]]></name> <description><![CDATA[asdgsdgsd sad sadg asdg asdg asdg asdg asdg asdg asdg asdg asdg asdg asdg]]></description> <keywords></keywords> <price>5.000000</price> <stock_quantity>36</stock_quantity> <reorder_quantity>0</reorder_quantity> <height>0.000000</height> <length>0.000000</length> <diameter>0.000000</diameter> <weight>0.000000</weight> <color>Black</color> <material>Leather</material> <barcode>883045300164</barcode> <release_date>2008-11-10</release_date> <images> <image>/AL10sds0XO/sdsdsd.jpg</image> <image>/sdsds/AL1sd00XOB.jpg</image> <image>/AL1sdsds00XO/sdsds.jpg</image> </images> <categories> <category code="80" video="0" parent="44">sdgsdgsdg</category> <category code="181" video="0" parent="172">Sleep &amp; Lounge</category> </categories> <manufacturer code="AL" video="0">Allure sdsds</manufacturer> <type code="LI" video="0">sdsfsdfsd</type> </product> </products> EOD; $tar_sku="SKUTARGET"; // this is the sku of the product block I need to have $pattern = "~<product .*?<sku>$tar_sku</sku>.*?</product>~is"; $returnValue = preg_match($pattern,$xml_str); echo '--'.$returnValue[0]; 

Не используйте регулярное выражение для анализа XML. Если ваша проблема связана с использованием памяти, использование регулярного выражения будет потреблять гораздо больше памяти, чем инкрементный синтаксический анализ. Поскольку регулярное выражение может работать только с строкой, вам понадобится не менее 100 МБ памяти, чтобы удерживать строку файла, прежде чем вы сможете что-либо с ней сделать. Если вы используете инкрементный синтаксический анализатор XML, вы можете использовать меньше памяти, чем размер файла.

Правильным инструментом для этого задания является XMLReader .

ТЛ; др

В этом ответе есть две XMLReader синтаксического анализа XMLReader :

  • getmatchingproducts_xml_expand() или getmatchingproducts_xml_noexpand() возвращает список всех согласованных продуктов. Использование памяти зависит от того, сколько совпадающих продуктов SKU находится в исходном xml.
  • Класс ProductMatcher – это Iterator (может использоваться в foreach ), который будет постепенно возвращать согласованные продукты в виде строки, DOMDocument или SimpleXMLElement . Он использует около 1 МБ памяти независимо от того, насколько большой ваш исходный XML или сколько товаров соответствует.

Тестовый файл

Я создал файл с образцом 120 МБ с использованием формата, который вы создали. Это код создания:

 function maketestfile() { $xml = <<<EOT <product active="1" on_sale="0" discountable="0"> <sku>{{SKU}}</sku> <name><![CDATA[LEATHER sdfsdf (NET)]]></name> <description><![CDATA[asdgsdgsd sad sadg asdg asdg asdg asdg asdg asdg asdg asdg asdg asdg asdg]]></description> <keywords></keywords> <price>5.000000</price> <stock_quantity>36</stock_quantity> <reorder_quantity>0</reorder_quantity> <height>0.000000</height> <length>0.000000</length> <diameter>0.000000</diameter> <weight>0.000000</weight> <color>Black</color> <material>Leather</material> <barcode>883045300164</barcode> <release_date>2008-11-10</release_date> <images> <image>/AL10sds0XO/sdsdsd.jpg</image> <image>/sdsds/AL1sd00XOB.jpg</image> <image>/AL1sdsds00XO/sdsds.jpg</image> </images> <categories> <category code="80" video="0" parent="44">sdgsdgsdg</category> <category code="181" video="0" parent="172">Sleep &amp; Lounge</category> </categories> <manufacturer code="AL" video="0">Allure sdsds</manufacturer> <type code="LI" video="0">sdsfsdfsd</type> </product> EOT; $fo = fopen('test2.xml', 'wb'); fwrite($fo, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"); fwrite($fo, "<products>\n"); $sku = array('SKUTARGET', 'XXXXXXXX', 'SKUY12345', '124432XXK', 'FOO1234BAR'); for ($i=0; $i < 100000; $i++) { shuffle($sku); fwrite($fo, str_replace('{{SKU}}', $sku[0], $xml)); } fwrite($fo, "</products>\n"); fclose($fo); } - function maketestfile() { $xml = <<<EOT <product active="1" on_sale="0" discountable="0"> <sku>{{SKU}}</sku> <name><![CDATA[LEATHER sdfsdf (NET)]]></name> <description><![CDATA[asdgsdgsd sad sadg asdg asdg asdg asdg asdg asdg asdg asdg asdg asdg asdg]]></description> <keywords></keywords> <price>5.000000</price> <stock_quantity>36</stock_quantity> <reorder_quantity>0</reorder_quantity> <height>0.000000</height> <length>0.000000</length> <diameter>0.000000</diameter> <weight>0.000000</weight> <color>Black</color> <material>Leather</material> <barcode>883045300164</barcode> <release_date>2008-11-10</release_date> <images> <image>/AL10sds0XO/sdsdsd.jpg</image> <image>/sdsds/AL1sd00XOB.jpg</image> <image>/AL1sdsds00XO/sdsds.jpg</image> </images> <categories> <category code="80" video="0" parent="44">sdgsdgsdg</category> <category code="181" video="0" parent="172">Sleep &amp; Lounge</category> </categories> <manufacturer code="AL" video="0">Allure sdsds</manufacturer> <type code="LI" video="0">sdsfsdfsd</type> </product> EOT; $fo = fopen('test2.xml', 'wb'); fwrite($fo, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"); fwrite($fo, "<products>\n"); $sku = array('SKUTARGET', 'XXXXXXXX', 'SKUY12345', '124432XXK', 'FOO1234BAR'); for ($i=0; $i < 100000; $i++) { shuffle($sku); fwrite($fo, str_replace('{{SKU}}', $sku[0], $xml)); } fwrite($fo, "</products>\n"); fclose($fo); } - function maketestfile() { $xml = <<<EOT <product active="1" on_sale="0" discountable="0"> <sku>{{SKU}}</sku> <name><![CDATA[LEATHER sdfsdf (NET)]]></name> <description><![CDATA[asdgsdgsd sad sadg asdg asdg asdg asdg asdg asdg asdg asdg asdg asdg asdg]]></description> <keywords></keywords> <price>5.000000</price> <stock_quantity>36</stock_quantity> <reorder_quantity>0</reorder_quantity> <height>0.000000</height> <length>0.000000</length> <diameter>0.000000</diameter> <weight>0.000000</weight> <color>Black</color> <material>Leather</material> <barcode>883045300164</barcode> <release_date>2008-11-10</release_date> <images> <image>/AL10sds0XO/sdsdsd.jpg</image> <image>/sdsds/AL1sd00XOB.jpg</image> <image>/AL1sdsds00XO/sdsds.jpg</image> </images> <categories> <category code="80" video="0" parent="44">sdgsdgsdg</category> <category code="181" video="0" parent="172">Sleep &amp; Lounge</category> </categories> <manufacturer code="AL" video="0">Allure sdsds</manufacturer> <type code="LI" video="0">sdsfsdfsd</type> </product> EOT; $fo = fopen('test2.xml', 'wb'); fwrite($fo, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"); fwrite($fo, "<products>\n"); $sku = array('SKUTARGET', 'XXXXXXXX', 'SKUY12345', '124432XXK', 'FOO1234BAR'); for ($i=0; $i < 100000; $i++) { shuffle($sku); fwrite($fo, str_replace('{{SKU}}', $sku[0], $xml)); } fwrite($fo, "</products>\n"); fclose($fo); } 

Функция памяти и синхронизации

 function trial($method, $args) { //prime the pump if (!function_exists($method)) throw BadFunctionCallException(); call_user_func_array($method, $args); $iter = 2; $runtime = 0; for ($i=0; $i < $iter; $i++) { $start = microtime(true); $res = call_user_func_array($method, $args); $runtime += microtime(true)-$start; } return array( 'peakmem' => memory_get_peak_usage(), 'mem' => memory_get_usage(), 'time' => $runtime/$iter, 'return' => $res, ); } function main($method, $filename) { $args = array($filename, 'SKUTARGET'); $res = trial($method, $args); echo "Found products: ",count($res['return']),"\n"; printf("%30s %3.2f %3.2f %4.3f\n", $method, $res['peakmem']/(1024*1024), $res['mem']/(1024*1024), $res['time']); } main($argv[1], $argv[2]); 

Regex vs XMLReader

Наконец, я протестировал эти функции. Первые два используют регулярные выражения, предлагаемые другими ответами, а третий использует XMLReader .

 function getmatchingproducts_regex1($xmlfile, $desiredsku) { $pattern = "~<product [^<]*<sku>".preg_quote($desiredsku,'~')."</sku>.*?</product>~Sus"; $xmlstr = file_get_contents($xmlfile); preg_match_all($pattern, $xmlstr, $matchingproducts); return $matchingproducts; } function getmatchingproducts_regex2($xmlfile, $desiredsku) { $pattern = "~<product [^<]*+<sku>".preg_quote($desiredsku,'~')."</sku>[^<]*(?:<(?!/product>)[^<]*)*</product>~Su"; $xmlstr = file_get_contents($xmlfile); preg_match_all($pattern, $xmlstr, $matchingproducts); return $matchingproducts; } function getmatchingproducts_xml_expand($xmlfile, $desiredsku) { $r = new XMLReader(); $r->open($xmlfile, null, LIBXML_COMPACT); $matchingproducts = array(); do { // advance to first product element $r->read(); } while ($r->nodeType!==XMLReader::NONE and !($r->nodeType===XMLReader::ELEMENT and $r->name==='product' and !$r->isEmptyElement)); while ($r->nodeType!==XMLReader::NONE) { if ($r->nodeType===XMLReader::ELEMENT and $r->name==='product' and !$r->isEmptyElement) { $dom = $r->expand(new DOMDocument('1.0','UTF-8')); $sxe = simplexml_import_dom($dom); if ((string) $sxe->sku===$desiredsku) { // Matching product found. // We have access to the <product> element and contents as: // * raw text via $r->readOuterXml() // * DOMDocument via $dom // * SimpleXML via $sxe // Pick the one you want and save: $matchingproducts[] = $r->readOuterXml(); // null the rest to be very conservative about memory $dom = $sxe = null; } } // optimization--skip to next product sibling $r->next('product'); } $r->close(); return $matchingproducts; } 

Наконец, я сохранил все это в файле и запустил его на своей двухъядерной 8GB-системе. (Числа – это пиковая память, конечная память и секунды на итерацию. «Найденные продукты» – это просто подтверждение правильного количества согласованных продуктов.)

 $ php xmlreader.php getmatchingproducts_xml_expand test2.xml Found products: 19969 getmatchingproducts_xml_expand 86.96 58.17 10.648 $ php xmlreader.php getmatchingproducts_regex1 test2.xml Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 1253 bytes) in xmlreader.php on line 72 $ php xmlreader.php getmatchingproducts_regex2 test2.xml Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 1253 bytes) in xmlreader.php on line 78 

Вы заметите, что методы регулярных выражений не могли даже работать без исчерпания доступной памяти! Кроме того, методы XMLReader (в дополнение к фактическому синтаксическому анализу XML) используют меньше памяти, чем размер файла. Я готов поспорить, что большая часть памяти getmatchingproducts_xml_expand является массивом $matchedproducts , а не синтаксическим $matchedproducts . Вы можете сократить использование памяти еще больше, обернув функцию парсера в классе, чтобы вы могли получить одно совпадение за раз.

Преимущество использования Regex заключается в том, что он намного быстрее . Вот еще одна попытка: ограничение памяти на 1 ГБ:

 $ php -d memory_limit=1G xmlreader.php getmatchingproducts_regex1 test2.xml Found products: 19968 getmatchingproducts_regex1 181.31 30.01 1.421 $ php -d memory_limit=1G xmlreader.php getmatchingproducts_regex2 test2.xml Found products: 19968 getmatchingproducts_regex2 181.31 30.01 0.906 

Вся эта скорость исходит из игнорирования правил разбора XML и обработки его как строки. (Интересно, что тот факт, что весь файл находится в памяти, не влияет на скорость XMLReader , а только на использование памяти.)

Если вам нужен быстрый доступ и использование низкой памяти, вам нужна какая-то индексация или база данных. Вы можете создать db с плоским файлом, используя sqlite , sqlite3 , dbm и загрузить его с помощью продуктов, с помощью SKU с использованием XMLReader . Затем вместо чтения XML-файла загрузите строку xml для этого продукта из db.

Просто для ударов я попробовал XMLReader разбора XMLReader который не использовал расширение, чтобы узнать, могу ли я экономить время или память. Однако разница была незначительной, а код намного менее ясен.

 function getmatchingproducts_xml_noexpand($xmlfile, $desiredsku) { $r = new XMLReader(); $r->open($xmlfile, null, LIBXML_COMPACT); $matchingproducts = array(); $candidateproduct = null; do { // advance to first product element $r->read(); } while ($r->nodeType!==XMLReader::NONE and !($r->nodeType===XMLReader::ELEMENT and $r->name==='product' and !$r->isEmptyElement)); while ($r->nodeType!==XMLReader::NONE) { if ($r->nodeType===XMLReader::ELEMENT and $r->name==='product' and !$r->isEmptyElement) { $candidateproduct = array($r->readOuterXML(), $r->depth); $r->read(); while ($r->depth > $candidateproduct[1]) { if ($r->nodeType===XMLReader::ELEMENT and $r->name==='sku' and $r->readString()===$desiredsku) { $matchingproducts[] = $candidateproduct[0]; $r->next('product'); break; } else { $r->next(); } } $candidateproduct = null; } else { $r->next(); } } $r->close(); return $matchingproducts; } $ php xmlreader.php getmatchingproducts_xml_noexpand test2.xml Found products: 19969 getmatchingproducts_xml_noexpand 86.95 58.17 13.716 

Возвращение результатов анализа пошагово

Еще одна реализация. Это, вероятно, так же эффективно, как это может получиться. Он анализирует тестовый файл 120 МБ с использованием менее 1 МБ памяти.

 class ProductMatcher implements Iterator { // return values for next() const R_STR = 'product_str'; // return string const R_DOM = 'product_dom'; // return DOMDocument const R_SXE = 'product_sxe'; // return SimpleXMLElement protected $reader; protected $productcount = null; protected $product_str = null; protected $product_dom = null; protected $product_sxe = null; protected $xmlfile; protected $returnmethod; public $desiredsku; function __construct($xmlfile, $desiredsku, $returnmethod=self::R_STR) { $this->xmlfile = $xmlfile; $this->desiredsku = $desiredsku; $this->setReturnMethod($returnmethod); } function __destruct() { if (isset($this->reader)) { $this->reader->close(); } } protected function _create() { $this->productcount = null; $this->reader = new XMLReader(); $this->reader->open($this->xmlfile, null, LIBXML_COMPACT); } protected function _start() { $r =& $this->reader; do { // advance to first product element $r->read(); } while ($r->nodeType!==XMLReader::NONE and !($r->nodeType===XMLReader::ELEMENT and $r->name==='product' and !$r->isEmptyElement)); } protected function advance() { $r =& $this->reader; $productfound = false; $this->product_str = $this->product_sxe = $this->product_dom = null; while ($r->nodeType!==XMLReader::NONE and !$productfound) { if ($r->nodeType===XMLReader::ELEMENT and $r->name==='product' and !$r->isEmptyElement) { // xmlreader_print($r); $dom = $r->expand(new DOMDocument('1.0','UTF-8')); $sxe = simplexml_import_dom($dom); if ((string) $sxe->sku===$this->desiredsku) { $this->product_str = $r->readOuterXml(); $this->product_sxe = $sxe; $this->product_dom = $dom; $productfound = true; $this->productcount = (isset($this->productcount)) ? $this->productcount+1 : 0; } } // optimization--skip to next product sibling $r->next('product'); } if (!$productfound) { $this->productcount = null; } } public function setReturnMethod($method) { $this->returnmethod = $method; } public function getReturnMethod() { return $this->returnmethod; } public function rewind() { $this->_create(); $this->_start(); $this->advance(); } public function valid() { return $this->productcount!==null; } public function current() { return $this->{$this->returnmethod}; } public function key() { return $this->productcount; } public function next() { $this->advance(); } } function timeProductMatcher($filename) { $matcher = new ProductMatcher($filename, 'SKUTARGET'); foreach ($matcher as $m) {} $runtime = 0; $iter = 2; for ($i=0; $i < $iter; $i++) { $start = microtime(true); $matcher = new ProductMatcher($filename, 'SKUTARGET'); foreach ($matcher as $n => $match) {} $runtime += microtime(true)-$start; } echo "Found products: ",$n+1, "\n"; printf("%30s %3.2f %3.2f %4.3f\n", 'ProductMatcher', memory_get_peak_usage()/(1024*1024), memory_get_usage()/(1024*1024), $runtime/$iter); } timeProductMatcher($argv[1]); 

Результаты:

 $ php xmlreader.php test2.xml Found products: 19969 ProductMatcher 0.76 0.75 10.394 

Расширенное использование примера:

 $matcher = new ProductMatcher($filename, 'SKUTARGET', ProductMatcher::R_SXE); foreach ($matcher as $product) { // $product is a SimpleXMLElement because we specified R_SXE (string) $product->sku === 'SKUTARGET'; // true } 

Если вы хотите только извлечь соответствующий бит <product>..</product> , используйте preg_match , а не preg_replace .

 $pattern = "~<product .*?<sku>$tar_sku</sku>.*?</product>~is"; $returnValues = preg_match($pat,$xml_str); 

Здесь $returnValues – это массив, который либо пуст, либо имеет один $returnValues[0] содержащий соответствующий бит XML, который вам $returnValues[0] .

Это связано с тем, что preg_match останавливается в первом матче. Если вы знаете, что во всем XML будет только один соответствующий SKUTARGET , используйте preg_match . Если вы считаете, что может быть больше одного и вы хотите извлечь все из них, используйте preg_match_all .

Регулярное выражение в основном такое же, как ваше, за исключением:

  • вы не можете использовать / чтобы разграничить регулярное выражение (например, /regex/ ), если внутри регулярного выражения есть внутренние / нерегулярные значения, если вы не избежите их. Таким образом, вам придется скрывать / in </sku> и т. Д. Я изменил разделитель на ~ поэтому мне не нужно беспокоиться о том, чтобы избежать моего внутреннего / .
  • <product * -> <product .* (первый только соответствует пробелам)
  • </sku>*</product> -> </sku>.*?</product> (первый только соответствует 0 или более > после /sku .
  • измененный жадный .* не-жадным .*? например, для предотвращения захвата XML, принадлежащего следующему продукту.

Не используйте regex для синтаксического анализа xml. Вместо этого используйте семейство xml-инструментов для php . Не совсем понятно, что вы хотите здесь сделать. Похоже, вы хотите выделить конкретный элемент из документа и заменить его чем-то другим. Вот пример .

[edit] Хорошо, поэтому, если вы хотите обрабатывать большие xml-файлы, используйте xmlreader .

Основная проблема с вашим кодом заключается в том, что вы неправильно используете preg_match . Возвращаемое значение представляет собой целое число, представляющее число, совпадающее с регулярным выражением, то есть 0 или 1 . Если вы хотите получить согласованный текст, вам необходимо предоставить массив для его хранения в:

 preg_match($pattern, $subject, $matches); 

Но есть проблема с регулярным выражением, которое вы увидите, если вы сделаете второй элемент <product> своей целью вместо первого. Матч по-прежнему начинается с первого элемента <product> , а затем продолжается до конца второго. Нехотя .*? недостаточно, чтобы гарантировать кратчайшее совпадение, поскольку оно влияет только на то, где заканчивается матч, а не там, где он начинается .

Вы должны убедиться, что после того, как он соответствует <product> тегу <product> , он не сможет больше соответствовать тегу <product> или </product> прежде чем он найдет <sku> . Предполагая, что <sku> всегда является первым элементом, указанным внутри элемента <product> , это простой вопрос об изменении первого .*? to [^<]* :

 "~<product [^<]*<sku>$tar_sku</sku>.*?</product>~is" 

Кроме того, учитывая размер файлов, может оказаться целесообразным сделать регулярное выражение максимально эффективным. С этой целью я сделал бы этот первый квантор обладателем – [^<]*+ – и заменил другой .*? с чем-то более детерминированным.

 "~<product [^<]*+<sku>$tar_sku</sku>[^<]*(?:<(?!/product>)[^<]*)*</product>~" 

Обратите внимание, что я также удалил модификаторы; флаг s теперь неактуальен, так как в регулярном выражении нет точек, и флаг i вероятно, никогда не понадобился, учитывая, что имена тегов XML чувствительны к регистру. Если SKU нет, вы можете применить флаг i только к той части регулярного выражения с встроенным модификатором, то есть (?i:...) :

 "~<product [^<]*+<sku>(?i:$tar_sku)</sku>[^<]*(?:<(?!/product>)[^<]*)*</product>~" 

Вот демо: http://ideone.com/mZqFz