Search code examples
phpxmlreportsimplexmlpreflight

using data from child element to select data in other element using simplexml in php


So, I'm using simplexml in php to display elements from an xml file onto a webpage. This is working fine when selecting a whole list child elements in one certain element. The thing is however, I need to select a number of rules in one element, and display the data attached to these certain rules found in another element.

To clarify, this a simplified version of my xml file (it contains everything I need):

<report>
    <profile_info>  
    <rules>

        <rule id="RUL1">
            <display_name>
            XMP does not have CreateDate entry in the XMP Basic Schema
            </display_name>
            <display_comment>
            This entry of the predefined XMP Basic Schema defines the date and time when the document has been created. It is required by some PDF-based ISO standards.
            </display_comment>
        </rule>

        <rule id="RUL133">
            <display_name>
            XMP does not have a VersionID entry in the XMP Media Management Schema
            </display_name>
            <display_comment>
            The VersionID in the XMP Media Management Schema (xmpMM) is the version identifier for respective resource. This entry is required by some PDF-based ISO standards for file identification.
            </display_comment>
        </rule>

        <rule id="RUL169">
            <display_name>
            Page does not have TrimBox or ArtBox
            </display_name>
            <display_comment>
            Either ArtBox or TrimBox should be defined for pages in a PDF file that are used in prepress. PDF/X ISO standards require the presence of one of these boxes.
            </display_comment>
        </rule>

    </rules>
</profile_info>


<results>
    <hits rule_id="RUL169" severity="Error">
    </hits>
    <hits rule_id="RUL133" severity="Error">
    </hits>
</results>
</report>

So far, I'm able to echo the entire list of rules with their display_name and display_comment using simplexml inside of php.

This is not what I want however. I want to be able to only show the child elements of the rules that actually gave an error, as displayed in the root element "results".

To sum up my problem: take the id's of the rules that gave an error in <results> and use those to display the display_name and display_comment shown in <rules>, another root element.

This the php code I have so far to list the entire list of rules that works, if that is of any help. (this works, but this is not what I want btw)

<?php

    if(file_exists('../uploads/reports/report.xml')){
    $xml = simplexml_load_file('../uploads/reports/report.xml');
    } 
    else{
    exit('Could not load the file ...');
    }

foreach ($xml->profile_info as $profile_info){
    foreach ($profile_info->rules as $rules){
        foreach ($rules->rule as $rule){

                echo '<div id="name">'.$rule->display_name.'</div>'.'<div id="comment">'.$rule
                    ->display_comment.'</div>';
?>

Thanks in advance!


Solution

  • The solution using SimpleXMLElement::xpath and array_map functions:

    $xml = simplexml_load_file('../uploads/reports/report.xml');
    ...
    $hits = $xml->xpath("results/hits/@rule_id");
    $ruleIds = array_map(function($v){    // getting search path for each needed rule
        return "profile_info/rules/rule[@id='". (string)$v. "']"; 
    }, $hits);
    
    foreach ($xml->xpath(implode(" | ", $ruleIds)) as $rule) {
        echo '<div id="name">'. $rule->display_name .'</div>'.
             '<div id="comment">'. $rule->display_comment .'</div>';
    }
    

    The "view-source" output:

            <div id="name">
            XMP does not have a VersionID entry in the XMP Media Management Schema
            </div><div id="comment">
            The VersionID in the XMP Media Management Schema (xmpMM) is the version identifier for respective resource. This entry is required by some PDF-based ISO standards for file identification.
            </div><div id="name">
            Page does not have TrimBox or ArtBox
            </div><div id="comment">
            Either ArtBox or TrimBox should be defined for pages in a PDF file that are used in prepress. PDF/X ISO standards require the presence of one of these boxes.
            </div>