Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get ALL elements of simplexml object

Tags:

php

simplexml

OK, I'm totally stumped here. I've found similar questions, but the answers don't seem to work for my specific problem. I've been working on this on and off for days.

I have this here simplexml object (it's actually much, much, MUCH longer than this, but I'm cutting out all the extraneous stuff so you'll actually look at it):

SimpleXMLElement Object
(
    [SubjectClassification] => Array
        (
            [0] => SimpleXMLElement Object
                (
                    [@attributes] => Array
                        (
                            [Authority] => Category Code
                            [Value] => s
                            [Id] => s
                        )

                )

            [1] => SimpleXMLElement Object
                (
                    [@attributes] => Array
                        (
                            [Authority] => Subject
                            [Value] => Sports
                            [Id] => 54df6c687df7100483dedf092526b43e
                        )

                )

            [2] => SimpleXMLElement Object
                (
                    [@attributes] => Array
                        (
                            [Authority] => Subject
                            [Value] => Professional baseball
                            [Id] => 20dd2c287e4e100488e5d0913b2d075c
                        )

                )

        )

)

I got this block of code by doing a print_r on a variable containing the following:

$subjects->SubjectClassification->children();

Now, I want to get at all the elements of the subjectClassification array. ALL of them! But when I do this:

$subjects->SubjectClassification;

Or this:

$subjects->SubjectClassification->children();

OR if I try to get all the array elements via a loop, all I get is this:

SimpleXMLElement Object
(
    [@attributes] => Array
        (
            [Authority] => Category Code
            [Value] => s
            [Id] => s
        )

)

Why? How can I get everything?

like image 210
boulevardofdef Avatar asked Jun 07 '13 18:06

boulevardofdef


3 Answers

You can use xpath to do this. Its the easiest way and most efficient I find and cuts down the need for lots of for loops and such to resolve items. To get all the nodes you want you can use:

if your xml is like this:

<Subjects>
<SubjectClassification>
</SubjectClassification>
<SubjectClassification>
</SubjectClassification>
<SubjectClassification>
</SubjectClassification>
</Subjects>

Then to get all subject classifications in an array you can do the following:

$subject_classifications = $xml->xpath("//SubjectClassification");

The xml variable refers to your main simplexml object i.e. the file you loaded using simplexml.

Then you can just iterate through the array using a foreach loop like this:

foreach($subject_classifications as $subject_classification){
echo (string) $subject_classification->Authority;
echo (string) $subject_classification->Value;
echo (string) $subject_classification->Id;
}

Your structure may vary but you get the idea anyway. You can see a good article from IBM here "Using Xpath With PHP":

like image 80
jiraiya Avatar answered Nov 19 '22 10:11

jiraiya


Because of the extent to which SimpleXML overloads PHP syntax, relying on print_r to figure out what's in a SimpleXML object, or what you can do with it, is not always helpful. (I've written a couple of debugging functions intended to be more comprehensive.) Ultimately, the reference should be to the XML structure itself, and knowledge of how SimpleXML works.

In this case, it looks from the output you provide that what you have is a list of elements all called SubjectClassification, and all siblings to each other. So you don't want to call $subjects->SubjectClassification->children(), because those nodes have no children.

Without a better idea of the underlying XML structure, it's hard to say more, so I'll save this incomplete answer for now.

like image 1
IMSoP Avatar answered Nov 19 '22 09:11

IMSoP


For all descendants (that are children, grand-children, grand-grand-children, grand-grand-... (you get the idea)) of <subjectClassification>s ("all the elements [...] ALL of them!" as you named it), you can make use of Xpath which supports such more advanced queries (at least I assume that is what you're looking for, your question does not give any detailed discription nor example what you mean by "all" specifically).

As for SimpleXML you can query elements (and attributes) only with Xpath, but as you need elements only, this is no show stopper:

$allOfThem = $subjects->xpath('./SubjectClassification//*');

The key point here is the Xpath expression:

./SubjectClassification//*

Per the dot . at the beginning it is relative to the context-node, which is $subjects in your case. Then looking for all elements that are descending to the direct child-element named SubjectClassification. This works per // (unspecified depth) and * (any element, star acts as a wildcard).

So hopefully this answers your question months after. I just stumbled over it by cleaning up some XML questions and perhaps this is useful for future reference as well.

like image 1
hakre Avatar answered Nov 19 '22 09:11

hakre