1

1: I want to get the amount of products in my XML file. I thought I can do that by a counter or marker-> lenght. But it isn't working. How can I solve that?

$gamesplanetPath = 'data/gamesplanet.xml';
$kinguinPath = 'data/kinguin.xml';
$onlinekeystorePath = 'data/onlinekeystore.xml';
$g2aPath = 'data/g2a.xml';

function countAd($gamesplanetPath){
    $dom = new DOMDocument('1.0', 'utf-8');
    $dom->preserveWhiteSpace = false;
    $dom->formatOutput = true;
    $dom->load($gamesplanetPath);

    $counter = 0;
    $root = $dom->documentElement;

    $marker = $root->getElementsByTagName('name');
    for($i = $marker->length - 1; $i >= 0 ; $i--){
        $counter = $counter + 1 ;
    }

    echo "Products: " . $counter ."\n";
}

2: My second question is, how can I check if the product, and I mean the url and description, contains a keyword like "steam"?

3: How can I append a child to every product and give that child a value?

XML which I want to load:

<?xml version="1.0" encoding="UTF-8"?>
    <products>
      <product>
        <name>Final Fantasy VII</name>
        <desc>Den Rollenspiel-Klassiker FINAL FANTASY VII gibt es jetzt für den PC, mit brandneuen Online-Features!</desc>
        <price>11.69</price>
        <price_base>12.99</price_base>
        <link>https://de.gamesplanet.com/game/final-fantasy-vii-download--1001-1</link>
        <publisher>Eidos - Square Enix</publisher>
        <category>RPG (Rollenspiel)</category>
        <ean/>
        <packshot>https://de.gamesplanet.com/acache/10/01/1/de/packshot-770bf6d03800b87dc0f9509f21e8d423.jpg</packshot>
      </product>

The first on is working in my cronjob.php class. In this class I download the XMLs and rename the values. I always make a DOMDocument like this:

$dom = new DOMDocument('1.0', 'utf-8');

So that I have no problem. Also I'm closing and opening my XML file repeatedly during the cronjob. But in the test.php class he is not opening the file because I get this error Message:

"D:\Anwendung\PHP 7\php-win.exe" C:\Users\Jan\PhpstormProjects\censored\test.php
PHP Warning:  DOMDocument::load(): Input is not proper UTF-8, indicate encoding !
Bytes: 0xE3 0xA4 0x63 0x68 in file:/C:/Users/Jan/PhpstormProjects/censored/data/gamesplanet.xml, line: 1423 in C:\Users\Jan\PhpstormProjects\censored\test.php on line 18
PHP Fatal error:  Uncaught Error: Call to a member function getElementsByTagName() on null in C:\Users\Jan\PhpstormProjects\censored\test.php:23
Stack trace:
#0 C:\Users\Jan\PhpstormProjects\censored\test.php(86): countAd('data/gamesplane...')
#1 {main}
  thrown in C:\Users\Jan\PhpstormProjects\censored\test.php on line 23

Process finished with exit code 255

I know that PHPStorm want to say me that the XML file is not in UTF-8. But the strange thing is that every time I open the XML file and close it I have no problem. Also it is very strange that the XML file is showing chars like "ä", "ö" and so on...

But in line 1423 I have: W㥣hter Von Mittelerde(Notepad++ View)

In Chrome I have: Wächter Von Mittelerde

Jan
  • 179
  • 1
  • 1
  • 8

1 Answers1

1

1: This should be working (proof), check contents that loaded into DOMDocument instance.

But no reason to manually traverse a nodes: $marker->length should contain the needed number.


2: I can suggest two ways:

a) Get list of all product nodes and filter those what have a link or desc child nodes with relevant nodeValue or textContent:

/**
 * Simple helper to test a node contents:
 */
function isSteamProduct(DOMNode $productNode, string $tag): bool
{
    $node = $productNode->getElementsByTagName($tag)->item(0);
    return strpos($node->nodeValue, 'steam') !== false;
}

...

foreach ($root->getElementsByTagName('product') as $productNode) {
    if (isSteamProduct($productNode, 'link') || isSteamProduct($productNode, 'desc')) {
        echo "Product URL or description contains 'steam' word";
    }
}

b) Using XPath:

$xpath = new DOMXPath($dom);
$xpath->query("//link[contains(text(), 'steam')]/..|//desc[contains(text(), 'steam')]/.."));

The expression above means: find all <link> and <desc> elements where node value contains a "steam" substring and get their parent nodes (<product>).


3: Just apply appendChild() to the every product element:

foreach ($root->getElementsByTagName('product') as $productNode) {
    $newElement = $dom->createElement('some-element-name', 'some value')
    $productNode->appendChild($newElement);
}
Timurib
  • 2,735
  • 16
  • 29
  • Thank you a lot, but I know now why it is not working...! See my answer below. So I can add code – Jan Jan 04 '17 at 22:44