简体   繁体   中英

Searching XML using XPath for multiple attributes in php

I found same topics but I didn't solve my problem :(

I want to search in XML with product code

this is my code;

$xml = simplexml_load_file('http://xml.aksel.com.tr/Xml.aspx?SK=d021da08&CK=50288');
                    $product_code = $_GET['s'];
                    $products = $xml->xpath("//STOK_KODU[contains(text(), '".$product_code."')]/STOK_ADI/GRUPKODU");

if I remove "/STOKADI/GRUPKODU", its working. But Product title, product image, product category didn't show. Where is the problem?

And my second problem, when I want to show all products; I see some products at least 4-5 times.

(Note: I work in WordPress)

I don't use simple_xml but the approach below, using DOMDocument and DOMXPath should be easy enough to port to simple_xml if desired. Initially I thought you were looking for child nodes of STOK_KODU but the structure of the XML suggests otherwise. The XPath query will find the node with the relevant $product_code from which you can easily find the parent and thus any/all of it's children.

$file='http://xml.aksel.com.tr/Xml.aspx?SK=d021da08&CK=50288';
#$file='c:/temp/Xml.xml'; /* saved locally to test */

$output=array();
$product_code=13775;

$query='//XMLWEBDATA/STOK_KODU[ contains( text(), "'.$product_code.'"  ) ]';

$dom=new DOMDocument;
$dom->load( $file );

$xp=new DOMXPath( $dom );
$col=$xp->query( $query );

if( $col && $col->length > 0 ){

    foreach( $col as $node ){
        /* get the parent */
        $parent=$node->parentNode;

        $data=array();
        for( $i=0; $i < $parent->childNodes->length; $i++ ){

            $tag=$parent->childNodes->item( $i )->tagName;
            $value=$parent->childNodes->item( $i )->nodeValue;

            if( !empty( $tag ) && !empty( $value ) ) $data[ $tag ]=$value;
        }
        $output[]=$data;
    }

    /* remove duplicates if there are any */
    $output=array_unique( $output );
}
$xp = $dom = null;


/* process the results accordingly */
if( !empty( $output ) ){
    foreach( $output as $obj ){
        printf('<pre>%s</pre>', urldecode( http_build_query( $obj, null, PHP_EOL ) ) );
    }
}

The output of which will be

STOK_KODU=13775
STOK_ADI=CHIP EPSON C3800 Black (S051127)
LISTEFIYAT=2,73
STOKBAKIYE1=16
GRUPKODU=DOLUM ÜRÜNLERİ GRUBU
KOD1=TONER DOLUM ÜRÜNLERİ
KOD2=ÇİPLER
PARABIRIMI=$
KULL5N=9500
RESIMURL=http://xml.aksel.com.tr/Photo.aspx?ID=22705&STOK=13775

To access each field as a variable ( which is what I understand your comment to be )

foreach( $col as $node ){
    /* get the parent */
    $parent=$node->parentNode;

    $data=array();
    for( $i=0; $i < $parent->childNodes->length; $i++ ){
        try{
            /* test node type to avoid errors */
            if( $parent->childNodes->item( $i )->nodeType==XML_ELEMENT_NODE ){

                $tag=$parent->childNodes->item( $i )->tagName;
                $value=$parent->childNodes->item( $i )->nodeValue;

                if( !empty( $tag ) && !empty( $value ) ) $data[ $tag ]=$value;
            }
        }catch( Exception $e ){
            echo $e->getMessage();
            continue;
        }
    }
    $output[]=$data;
}

and to access as variables, use extract

            if( !empty( $output ) ){
                foreach( $output as $obj ){

                    extract( $obj );
                    printf("<pre>%s\n%s\n%s</pre>", $STOK_KODU, $STOK_ADI, $GRUPKODU );

                }
            }

If you look at the structure of the XML, the GRUPKODU and STOKADI are elements at the same level. So trying to access these in you XPath at the same time isn't going to work. If instead you look for the XMLWEBDATA element your after, you can then access these elements inside this element. This XPath looks for an XMLWEBDATA with a STOK_KODU with content that contains the product code your after, then using foreach to print out each match, it outputs the two values your after...

$products = $xml->xpath("//XMLWEBDATA[STOK_KODU[contains(text(), '".$product_code."')]]");
foreach ( $products as $product )   {
    echo (string)$product->STOK_ADI.PHP_EOL;
    echo (string)$product->GRUPKODU.PHP_EOL;
}

(I only cast the return values to strings as this is needed if assigning to other values, echo will automatically cast it anyway and it can cause confusing results when used in assignments)

If I set

$product_code = 14037;

This outputs

EPSON T2711XL (27XL) > WF3620,3640,7110,7610,7620  Black
TÜKETİM ÜRÜNLERİ GRUBU

Note: You may want to use....

$products = $xml->xpath("//XMLWEBDATA[STOK_KODU='".$product_code."']");

to ensure that you only find a code that fully matches in case there are cases where it will match parts of other codes.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM