-->

How can I edit my code to echo the data of child&#

2019-01-20 06:23发布

问题:

I am new in XMLReader, and I think is kind of hard to find tutorials/code or something advanced to get examples. My question is how can I transform the code I have now, so if I search (through a form) the term jQuery will give me the opportunity to output the value of <info></info> (and later other elements) in every <name></name> that is found in ?

This is the code that output the names of the books.

<?php
$reader = new XMLReader();
$reader->open("books.xml");
while ($reader->read()) {
   switch ($reader->nodeType) {
   case (XMLREADER::ELEMENT):

                  if ($reader->localName == "name") {
                     $reader->read();
                     echo $reader->value;
                     break;
                  }}}
?>

the xml file

<?xml version="1.0" encoding="ISO-8859-1"?>
<library>
    <book isbn="781">
        <name>SCJP 1.5</name>
        <info>Sun Certified Java Programmer book</info>
    </book>
    <book isbn="194">
        <name>jQuery is Awesome!</name>
        <info>jQuery Reference Book</info>
    </book> 
    <book isbn="199">
        <name>jQuery 101</name>
        <info>All you need to know about jQuery</info>
    </book> 
</library>

回答1:

If you're bound to XMLReader for sequential parsing then you can build some parser based on it.

One method to simplify the parsing operation is to encapsulate it into an iterator, especially if you're working on a sequence. For example with an iterator named XMLBookIterator you could just foreach over all books while the data is being parsed:

$books = new XMLBookIterator($file);

foreach($books as $key => $book)
{
    echo 'book (', $key, '):', "\n";
    print_r($book);
}

A result could look like this with your example data:

book (0):
stdClass Object
(
    [isbn] => 781
    [name] => SCJP 1.5
    [info] => Sun Certified Java Programmer book
)
book (1):
stdClass Object
(
    [isbn] => 194
    [name] => jQuery is Awesome!
    [info] => jQuery Reference Book
)
book (2):
stdClass Object
(
    [isbn] => 199
    [name] => jQuery 101
    [info] => All you need to know about jQuery
)

Then it's only left to filter the books based on your term. This can be implemented into a FilterIterator, let's call it BookFilterIterator:

$filtered = new BookFilterIterator($books, 'jQuery');

foreach($filtered as $key => $book)
{
    echo 'book (', $key, '):', "\n";
    print_r($book);
}

The output would then be reduced to only the matching books:

book (1):
stdClass Object
(
    [isbn] => 194
    [name] => jQuery is Awesome!
    [info] => jQuery Reference Book
)
book (2):
stdClass Object
(
    [isbn] => 199
    [name] => jQuery 101
    [info] => All you need to know about jQuery
)

The only thing left is the actual code that does this. It's a bit longer, in it's heart - the next() function inside the iterator you will find a state-based parser that is reading over the XML like you already started with in your question. The difference is, that it has some sort of state which helps to fill up the current book entry which is stored as a private member of the class.

Code, Demo

The demo code uses you XML as string which is then converted into a pseudo "file" via $file = 'data://text/plain;base64,'.base64_encode($xml);. The iterator works with any filename, it just get's passed to XMLReader anyway, so for large data, use a file.



回答2:

Try simplexml -- it's better:

<?php
$books  = simplexml_load_file('books.xml');
$search = 'jquery';
foreach ($books->book as $book) {
    if (preg_match('/' . preg_quote($search) . '/i', $book->name)) {
        echo $book->name . ' (' . $book->info . ')<br/>';
    }
}