使用PHP解析xml caaml文件

I'm trying to parse an xml file with CAAML standard. Check it out here!

I want to list all the sections with region code AT7R9

I found this code but don't know how to parse the region code sections:

$doc = new DOMDocument();
$doc->load('lws.xml');

$xpath = new DOMXpath($doc);
$xpath->registerNamespace("caaml", "http://caaml.org/Schemas/V5.0/Profiles/BulletinEAWS");

if ($doc->schemaValidate('http://caaml.org/Schemas/V5.0/Profiles/BulletinEAWS/CAAMLv5_BulletinEAWS.xsd')) {

    echo '<ul>'."
";
    echo '    <li>dateTimeReport: <img src="'.$xpath->evaluate("//caaml:fileReferenceURI")->item(0)->nodeValue.'" alt="Lawinenlagebericht vom '.$xpath->evaluate("//caaml:MetaData/caaml:dateTimeReport")->item(0)->nodeValue.'"></li>'."
";
    echo '    <li>dateTimeReport: '.$xpath->evaluate("//caaml:MetaData/caaml:dateTimeReport")->item(0)->nodeValue.'</li>'."
";
    echo '    <li>srcRef: '.$xpath->evaluate("//caaml:MetaData/caaml:srcRef/@*[local-name()='href']")->item(0)->nodeValue.'</li>'."
";
    echo '    <li>comment: '.$xpath->evaluate("//caaml:BulletinMeasurements/caaml:comment")->item(0)->nodeValue.'</li>'."
";
    echo '    <li>Warnstufe R9: '.$xpath->evaluate("./caaml:locRef")->item(0)->nodeValue.'</li>'."
";

    echo '</ul>'."
";

}

Can someone help me out with a snippet that parses the DangerRating section of R9 please?

This is the xml section:

    <caaml:DangerRating>
      <caaml:locRef xlink:href="AT7R9"/>
      <caaml:validTime>
        <caaml:TimePeriod>
          <caaml:beginPosition>2015-04-13T00:00:00+02:00</caaml:beginPosition>
          <caaml:endPosition>2015-04-13T11:59:59+02:00</caaml:endPosition>
        </caaml:TimePeriod>
      </caaml:validTime>
      <caaml:validElevation>
        <caaml:ElevationRange uom="m">
          <caaml:beginPosition>2200</caaml:beginPosition>
        </caaml:ElevationRange>
      </caaml:validElevation>
      <caaml:mainValue>1</caaml:mainValue>
    </caaml:DangerRating>
    <caaml:DangerRating>
      <caaml:locRef xlink:href="AT7R9"/>
      <caaml:validTime>
        <caaml:TimePeriod>
          <caaml:beginPosition>2015-04-13T00:00:00+02:00</caaml:beginPosition>
          <caaml:endPosition>2015-04-13T11:59:59+02:00</caaml:endPosition>
        </caaml:TimePeriod>
      </caaml:validTime>
      <caaml:validElevation>
        <caaml:ElevationRange uom="m">
          <caaml:endPosition>2200</caaml:endPosition>
        </caaml:ElevationRange>
      </caaml:validElevation>
      <caaml:mainValue>2</caaml:mainValue>
    </caaml:DangerRating>
    <caaml:DangerRating>
      <caaml:locRef xlink:href="AT7R9"/>
      <caaml:validTime>
        <caaml:TimePeriod>
          <caaml:beginPosition>2015-04-13T12:00:00+02:00</caaml:beginPosition>
          <caaml:endPosition>2015-04-13T23:59:59+02:00</caaml:endPosition>
        </caaml:TimePeriod>
      </caaml:validTime>
      <caaml:validElevation>
        <caaml:ElevationRange uom="m">
          <caaml:beginPosition>2800</caaml:beginPosition>
        </caaml:ElevationRange>
      </caaml:validElevation>
      <caaml:mainValue>2</caaml:mainValue>
    </caaml:DangerRating>
    <caaml:DangerRating>
      <caaml:locRef xlink:href="AT7R9"/>
      <caaml:validTime>
        <caaml:TimePeriod>
          <caaml:beginPosition>2015-04-13T12:00:00+02:00</caaml:beginPosition>
          <caaml:endPosition>2015-04-13T23:59:59+02:00</caaml:endPosition>
        </caaml:TimePeriod>
      </caaml:validTime>
      <caaml:validElevation>
        <caaml:ElevationRange uom="m">
          <caaml:endPosition>2800</caaml:endPosition>
        </caaml:ElevationRange>
      </caaml:validElevation>
      <caaml:mainValue>3</caaml:mainValue>
    </caaml:DangerRating>
    <caaml:DangerRating> 

I think you can use this as your xpath expression:

$domNodeList = $xpath->evaluate("//caaml:DangerRating[descendant::caaml:locRef/@xlink:href='AT7R9']");

The $xpath->evaluate will return a DOMNodeList which you can loop using a foreach.

Maybe this setup can help you:

<?php
if ($doc->schemaValidate('http://caaml.org/Schemas/V5.0/Profiles/BulletinEAWS/CAAMLv5_BulletinEAWS.xsd')) {

    $domNodeList = $xpath->evaluate("//caaml:DangerRating[descendant::caaml:locRef/@xlink:href='AT7R9']");

    // This will give you 4 DOMElement's where $dnl->nodeName is 'caaml:DangerRating'
    foreach ($domNodeList as $dnl) {

        foreach ($dnl->childNodes as $childNode) {

            // For example check if the $childNode is a DOMElement
            if ($childNode->nodeType === 1) {
                // etc..
            }
        }
    }
}

thx for your help, but i cant get it to work on your way but it woul dbe the nicer peace of code :/

i did it like this now:

# Setzt den Array Index wieder zurück auf 0
function fix_keys($array) {
    $numberCheck = false;
        foreach ($array as $k => $val) {
            if (is_array($val)) $array[$k] = fix_keys($val); //recurse
            if (is_numeric($k)) $numberCheck = true;
        }
            if ($numberCheck === true) {
                return array_values($array);
            } else {
                return $array;
            }
}


# XML File auslesen
$xmlfile = new DOMDocument();
$lws = array();

$xmlfile->load('lws.xml'); // Source File auslesen, Originl LWS( https://apps.tirol.gv.at/lwd/produkte/LLBTirol.xml )

$xpath = new DOMXpath($xmlfile);
$xpath->registerNamespace("caaml", "http://caaml.org/Schemas/V5.0/Profiles/BulletinEAWS");
$xpath->registerNamespace("xlink", "http://www.w3.org/1999/xlink");

# echo "Lawinenwarnstufe in den R9 Zillertaler Alpen!<br>";
foreach ($xpath->evaluate('//caaml:DangerRating') as $dangerRating) {

    $locRef = $xpath->evaluate('string(caaml:locRef/@xlink:href)', $dangerRating );

    if ($locRef == "AT7R9") {

        $seehoehe = $xpath->evaluate('string(caaml:validElevation/caaml:ElevationRange/caaml:endPosition)', $dangerRating );
        if(empty($seehoehe)){
            $lws[$i][] = "0";
        }else{      
            $lws[$i][] = $xpath->evaluate('string(caaml:validElevation/caaml:ElevationRange/caaml:endPosition)', $dangerRating );
        }
        $lws[$i][] = $xpath->evaluate('string(caaml:mainValue)', $dangerRating );
    }
    $i++;
}

# Arrayindex auf 0 setzen;
$lws = fix_keys($lws);

#### Wenn 4 Angaben vorhanden sind gilt folgender Aufbau 1+2 Vormittags / 3+4 Nachmittags
#### $lws[i][0] = Seehöheader
#### $lws[i][1] = Warnstufe
echo "Vormittag:";
echo " < ".$lws[1][0]."m = ".$lws[0][1].", "; 
echo " > ".$lws[1][0]."m = ".$lws[1][1]."; ";
echo "<br>";
echo "Nachmittag:"; 
echo " < ".$lws[3][0]."m = ".$lws[2][1].", ";
echo " > ".$lws[3][0]."m = ".$lws[3][1]."; ";

Your variant ist much shorter but i cant get the whitespace and empty lines out of the array.

# XML File auslesen
$xmlfile = new DOMDocument();
$lws = array();
$i=1;
$xmlfile->load('lws.xml'); // Source File auslesen, Originl LWS( https://apps.tirol.gv.at/lwd/produkte/LLBTirol.xml )

$xpath = new DOMXpath($xmlfile);
$xpath->registerNamespace("caaml", "http://caaml.org/Schemas/V5.0/Profiles/BulletinEAWS");
$xpath->registerNamespace("xlink", "http://www.w3.org/1999/xlink");

if ($xmlfile->schemaValidate('http://caaml.org/Schemas/V5.0/Profiles/BulletinEAWS/CAAMLv5_BulletinEAWS.xsd')) {

    $domNodeList = $xpath->evaluate("//caaml:DangerRating[descendant::caaml:locRef/@xlink:href='AT7R9']");

    // This will give you 4 DOMElement's where $dnl->nodeName is 'caaml:DangerRating'
    foreach ($domNodeList as $dnl) {

        //test output
        echo "Eintrag".$i." = ".$dnl->nodeValue."<br>";

        $lws[] = $dnl->nodeValue;
        $i++;
    }
}   
$clean_data = array_merge( array_filter($lws) );

this give me a correct output if i print it during the foreach but if i write it into an array i get this:

Eintrag1 = 2015-04-13T00:00:00+02:00 2015-04-13T11:59:59+02:00 2200 1
Eintrag2 = 2015-04-13T00:00:00+02:00 2015-04-13T11:59:59+02:00 2200 2
Eintrag3 = 2015-04-13T12:00:00+02:00 2015-04-13T23:59:59+02:00 2800 2
Eintrag4 = 2015-04-13T12:00:00+02:00 2015-04-13T23:59:59+02:00 2800 3

Array
(
    [0] => 



              2015-04-13T00:00:00+02:00
              2015-04-13T11:59:59+02:00




              2200


          1

    [1] => 



              2015-04-13T00:00:00+02:00
              2015-04-13T11:59:59+02:00




              2200


          2

    [2] => 



              2015-04-13T12:00:00+02:00
              2015-04-13T23:59:59+02:00




              2800


          2

    [3] => 



              2015-04-13T12:00:00+02:00
              2015-04-13T23:59:59+02:00




              2800


          3

)

if i could get that to work i need to explode the data so i could use them seperatly.

may you have the answer :) otherwise i use my version

thx for your help!!