Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
65 views
in Technique[技术] by (71.8m points)

How to get XML attribute values using PHP

I am trying to get value from xml attributes. but i am only getting 1st bookshelf stocks values but 2nd stocks value i am not getting. how i can show Empty when there is no stock value like in the book ID="5"

XML test.xml

<?xml version="1.0" encoding="utf-8"?>
<bookstore Code="111">
    <bookshelf  Date="01/26/2021" Time="7:35 PM" Note=" ">
        <book ID="3" Name="website1">
            <stock price="10"  Name="Name5"/>
        </book>
        <book ID="4" Name="website 2">
            <stock price="12"  Name="Name2"/>
        </book>
        <book ID="7" Name="website 3">
            <stock price="10.50" Name="Name3" />
        </book>
        <book ID="5" Name="website 4" />
    </bookshelf>
    <bookshelf  Date="01/25/2021" Time="7:35 PM" Note=" ">
        <book ID="3" Name="website1"/>
        <book ID="4" Name="website 2"/>
        <book ID="7" Name="website 3"/>
        <book ID="5" Name="website 4" />
    </bookshelf>
</bookstore>

PHP CODE

<?php $mybooks = simplexml_load_file('test.xml');?>
<table width="100%" border="1">
  <tbody>
    <tr>
      <td>Bookshelf Date</td>
      <td>website1</td>
      <td>website2</td>
      <td>website3</td>
      <td>website4</td>
    </tr>
  <tr><td><?php  echo $bookshelf['Date']; ?></td>
      <?php
      foreach($mybooks->bookshelf->book as $d) {
      $d['Name'].' '.$d['ID'].'<br>';
      foreach( $d->stock as $stocks) {
      $stocks['price'].' '.$stocks['Name']."
";
      ?>
      <td><?php  echo $stocks['price'].' '.$stocks['Name']."
"; ?> </td>
     <?php }} ?></tr></tbody>
</table>

Updated: what if from one bookshelf -> book getting no data. how can i check it if that bookshelf getting data or hide it from showing it in result.

question from:https://stackoverflow.com/questions/65901273/how-to-get-xml-attribute-values-using-php

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

I offer to you 3 methods to accomplish your end goal - admittedly only one uses simple_xml

Method #1: Simple XML As you wish to display ALL websites per row in the table you need nested queries. The outer query to return the rows ( bookshelfs ) and the inner query to return the books on that bookshelf. When it comes to the stock node that does not exist for particular books I used a ternary operator to select another value if the stock tag did not exist.

<?php
    $xmlfile='test.xml';
    $mybooks = simplexml_load_file( $xmlfile );
?>
<table border=1 cellspacing=5 cellpadding=5>
    <thead>
        <tr>
            <th>Bookshelf Date</th>
            <th>Website 1</th>
            <th>Stock</th>
            <th>Website 2</th>
            <th>Stock</th>
            <th>Website 3</th>
            <th>Stock</th>
            <th>Website 4</th>
            <th>Stock</th>
        </tr>
    </thead>
    <tbody>

    <?php
        foreach( $mybooks->bookshelf as $shelf ) {
    ?>
        <tr>
            <td><?php echo $shelf['Date'];?></td>
        <?php
            foreach( $shelf->book as $book ){
        ?>
            <td><?php echo $book['Name'];?></td>
            <td>
            <?php
                $stock=$book->stock ? $book->stock['price'] : 'None';
                echo $stock;
            ?>
            </td>
        <?php
            }
        ?>
        </tr>
    <?php
        }
    ?>
    </tbody>
</table>

Which outputs: ex1

Method #2: DOMDocument & XPath

<!DOCTYPE html>
<html lang='en'>
    <head>
        <meta charset='utf-8' />
        <title></title>
    </head>
    <body>
        <table border=1 cellspacing=5 cellpadding=5>
            <tr>
                <th>Bookshelf Date</th>
                <th>Website 1</th>
                <th>Stock</th>
                <th>Website 2</th>
                <th>Stock</th>
                <th>Website 3</th>
                <th>Stock</th>
                <th>Website 4</th>
                <th>Stock</th>
            </tr>
        
        <?php
            
            $xml='<?xml version="1.0"?>
                <bookstore Code="111">
                    <bookshelf Date="01/26/2021" Time="7:35 PM" Note=" ">
                        <book ID="3" Name="website 1">
                            <stock price="10"  Name="Name5"/>
                        </book>
                        <book ID="4" Name="website 2">
                            <stock price="12"  Name="Name2"/>
                        </book>
                        <book ID="7" Name="website 3">
                            <stock price="10.50" Name="Name3" />
                        </book>
                        <book ID="5" Name="website 4" />
                    </bookshelf>
                    <bookshelf Date="01/26/2021" Time="7:35 PM" Note=" ">
                        <book ID="3" Name="website 1">
                            <stock price="110"  Name="Name5"/>
                        </book>
                        <book ID="4" Name="website 2">
                            <stock price="112"  Name="Name2"/>
                        </book>
                        <book ID="7" Name="website 3">
                            <stock price="110.50" Name="Name3" />
                        </book>
                        <book ID="5" Name="website 4" />
                    </bookshelf>
                </bookstore>';
                
            
            $dom=new DOMDocument;
            $dom->loadXML( $xml );
            
            $xp=new DOMXPath( $dom );
            $expr='//bookshelf';
            
            $col=$xp->query( $expr );
            if( $col->length > 0 ){
                foreach( $col as $shelf ){
                    
                    $tmp=[ $shelf->getAttribute('Date') . ' ' . $shelf->getAttribute('Time') ];
                    
                    $bookcol=$xp->query('book', $shelf);
                    if( $bookcol->length > 0 ){
                        foreach( $bookcol as $book ){
                            
                            $stock=$xp->query('stock', $book );
                            $stock=( $stock->length > 0 ) ? $stock->item(0)->getAttribute('price') : 'None';    
                            
                            $tmp[]=$book->getAttribute('Name');
                            $tmp[]=$stock;
                        }
                    }
                    
                    
                    printf('
                        <tr>
                            <td>%s</td>
                            <td>%s</td>
                            <td>%s</td>
                            <td>%s</td>
                            <td>%s</td>
                            <td>%s</td>
                            <td>%s</td>
                            <td>%s</td>
                            <td>%s</td>
                        </tr>',
                        ...$tmp
                    );
                }
            }
        ?>
        </table>
    </body>
</html>

Which outputs: ex2

Method #3: DOM Document & XSLTProcessor - XSL Stylesheets

The XSL stylesheet

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <!-- we want to output a portion of html -->
    <xsl:output method='html' standalone='yes' indent='yes' encoding='utf-8'/>
    <xsl:template match="/">
        <style>
            table.xml{
                border:1px solid gray;
                display:table;
                border-collapse:collapse;
                border-spacing:0px;
                empty-cells:show;
                table-layout:auto;
                font-family:Verdana, Geneva, Arial, Helvetica, sans-serif;
                font-size:0.8rem;
            }
            table.xml tr:first-of-type{
                background:#2f4f4f;
                color:white;
            }
            table.xml tr:nth-of-type( even ) td{
                background:aliceblue;
            }
            table.xml td{
                margin:0;
                padding:5px;
                border-bottom:1px dotted rgba(133,133,133,0.5);
            }
        </style>
        <table class='xml' border='1' cellspacing='5' cellpadding='5'>
            <tr>
                <th>Bookshelf Date</th>
                
                <th>Website 1</th>
                <th>Stock</th>
                
                <th>Website 2</th>
                <th>Stock</th>
                
                <th>Website 3</th>
                <th>Stock</th>
                
                <th>Website 4</th>
                <th>Stock</th>
            </tr>
            <xsl:for-each select="bookstore/bookshelf">
            <tr>
                <xsl:attribute name='data-id'>
                    <xsl:value-of select="book/@ID"/>
                </xsl:attribute>
                <td><xsl:value-of select="@Date"/></td>
                <xsl:for-each select="book">
                    <td><xsl:value-of select="@Name"/></td>
                    <td>
                        <xsl:attribute name='data-name'>
                            <xsl:value-of select="stock/@Name"/>
                        </xsl:attribute>
                        <xsl:choose>
                            <xsl:when test="stock/@price !=''">
                                <xsl:value-of select="stock/@price"/>
                            </xsl:when>
                            <xsl:otherwise>
                                None
                            </xsl:otherwise>
                        </xsl:choose>
                    </td>
                </xsl:for-each>
            </tr>
            </xsl:for-each>
        </table>
    </xsl:template>
</xsl:stylesheet>

and the PHP to load and process it

<?php
    $xmlfile='c:/wwwroot/xml/bookstore.xml';
    $xslfile='c:/wwwroot/xsl/bookstore.xsl';

    $dom=new DOMDocument;
    $dom->load( $xmlfile );
    
    $css=new DOMDocument;
    $css->load( $xslfile );
    
    $xsl=new XSLTProcessor;
    $xsl->importStyleSheet( $css );
    $html=$xsl->transformToXML( $dom );
    
    header('Content-Type: text/html');
    exit( $html );
?>

Which outputs: ex3

update

Based upon modified XML and comment above:

<?php
    
    $data=[];

    foreach( $mybooks->bookshelf as $shelf ) {
        
        $row=[];
        $books=$shelf->children();
        
        if( !empty( $books ) ){
            if( $books->children() && count( $books->children() ) > 0 ){
                
                $row[]=sprintf('<tr data-date="%s" data-time="%s" data-note="%s">', $shelf['Date'], $shelf['Time'], $shelf['Note'] );
                $row[]=sprintf('<td>%s</td>',implode(', ', [ $shelf['Date'], $shelf['Time'] ] ) );
                
                $cells=[];
                foreach( $books as $book ){
                    if( $book->stock ){
                        $cells[]=sprintf('<td>%s</td>', $book['Name'] );
                        $cells[]=sprintf('<td>%s</td>',$book->stock['price']);
                    }
                }
                $row[]=implode( PHP_EOL, $cells );
                $row[]='</tr>';
            }
        }
        #append
        $data[]=implode( PHP_EOL, $row );
   

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...