Nipper studio XML parser

120 Views Asked by At
<section index="2.3" title="No HTTP(S) Server Session Timeout or HTTP(S) Server Idle Timeout Set" ref="ADMINISTRATION.WEBTIMEOUT.NO.HTTP.OR.HTTPS.SESSION.OR.IDLE.TIMEOUT.four">
    <issuedetails>
        <devices>
            <device name="Switch" type="Cisco Catalyst Switch" osversion="16.3" />
        </devices>
        <ratings type="Nipperv1">
            <rating>High</rating>
            <impact>Critical</impact>
            <ease>Easy</ease>
            <fix>Quick</fix>
            <FindingID>NSA-ADMIN-046</FindingID>
            <classif>Administration</classif>
        </ratings>
    </issuedetails>
    <section index="2.3.1" title="Finding" ref="FINDING">
    </section>
    <section index="2.3.4" title="Recommendation" ref="RECOMMENDATION">
        <text>Nipper Studio recommends that a HTTP(S) server session timeout period of 10 minutes or less should be configured.</text>
        <text>Notes for Cisco Catalyst Switch devices:</text>
        <text>The HTTP server timeout can be configured with the following command:<code><command>ip http timeout-policy idle <cmduser>seconds</cmduser> life <cmduser>seconds</cmduser> requests <cmduser>number</cmduser></command>
        </code>
        </text>

XML Parser:

$commands = $section->xpath('section[4]/text/code/command');
$object->commands = "";
foreach($commands as $command)
{
    $object->commands .=  $command;
    $cmdusers = $command->xpath('cmduser');
    foreach($cmdusers as $cmduser){
        $object->commands .=  $cmduser;
    }
    $object->commands .=  "<br>";
}
echo "commands : <br>".$object->commands;
echo "<be>";

Output:

ip http timeout-policy idle seconds life seconds requests number

But it came like this

ip http timeout-policy idle life requests secondssecondsnumber
2

There are 2 best solutions below

7
Siebe Jongebloed On

In this case you could use just one XPath:

$commands = $section->xpath('section[4]/text/code/command//text()');
0
hakre On

You have already seen that your expectation does not match with the actual results.

This is merely a limitation with SimpleXML so it is a bit of in the "wrong tool for the job" category. But read on, it's versatile.

What makes it hard for you as that you're using the SimpleXML parser for XML with a structure it is not well suited for - at least at this place.

The problematic part is looking for text-data that goes across multiple element nodes.

As outlined for Echoing the contents of an xml-file with nested tags in an answer by cOle2:

Currently your $output is a SimpleXMLElement and when you echo it the internal toString() method is called. Per the notes, this method does not return text content that is inside this element's children which is why certain text is excluded.

A way to obtain the text-content while making use of SimpleXML is to make use of the DOM sister-library, which is similar to my answer to the other question and it is an easy import operation and then fetching the property:

$commands = $section->xpath('section[4]/text/code/command');
$object->commands = "";
foreach($commands as $command)
{
    $object->commands .=  dom_import_simplexml($command)->textContent;
                                  ^^^^            ^^^         ^^^^
    ...

As a rule of thumb, SimpleXML is weak with XML text-nodes. There aren't any specifically in its API and string values represent leaf-element-nodes text content. Other element nodes string content may appear incomplete and mis-ordered - like you could experience it.