简体   繁体   中英

DOMDocument::loadXML() for parts of XML

Simple XML templates like these ones :

structure.xml :

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<document>
<book>first book</book>
<book>second book</book>
((other_books))
</document>

book_element.xml :

<book>((name))</book>

And this test :

    <?php
Header("Content-type: text/xml; charset=UTF-8");
class XMLTemplate extends DOMDocument
{
    private $_content_storage;
    private $_filepath;
    private $_tags;

    public function XMLTemplate( $sFilePath )
    {
        if( !file_exists( $sFilePath ) ) throw new Exception("file not found");

        $this->_filepath = $sFilePath;
        $this->_tags = [];
        $this->_content_storage = file_get_contents( $this->_filepath );
    }

    public function Get()
    {
        $this->merge();
        $this->loadXML( $this->_content_storage );
        return $this->saveXML();
    }

    public function SetTag( $sTagName, $sReplacement )
    {
        $this->_tags[ $sTagName ] = $sReplacement;  
    }

    private function merge()
    {
        foreach( $this->_tags as $k=>$v)
        {
            $this->_content_storage = preg_replace(
                "/\({2}". $k ."\){2}/i",
                $v,
                $this->_content_storage
            );
        }
        $this->_content_storage = preg_replace(
            "/\({2}[a-z0-9_\-]+\){2}/i",
            "",
            $this->_content_storage
        );
    }
}

$aBooks = [
    "troisième livre",
    "quatrième livre"   
];

$Books = "";

foreach( $aBooks as $bookName )
{
    $XMLBook = new XMLTemplate("book_element.xml");
    $XMLBook->SetTag( "name", $bookName );
    $Books .= $XMLBook->Get();
}

$XMLTemplate = new XMLTemplate("test.xml");

$XMLTemplate->SetTag("other_books", $Books);
echo $XMLTemplate->Get();
?>

Give me error :

Warning: DOMDocument::loadXML(): XML declaration allowed only at the start of the document in Entity, line: 5

Because loadXML() method add automatically the declaration to the content, but i need to inject parts of xml in the final template like above. How to disable this annoying auto adding and let me use my declaration ? Or another idea to conturn the problem ?

If you dislike the error and you want to save the document you'd like to merge without the XML declaration, just save the document element instead of the whole document.

See both variants in the following example-code ( online-demo ):

$doc = new DOMDocument();
$doc->loadXML('<root><child/></root>');

echo "The whole doc:\n\n";
echo $doc->saveXML();

echo "\n\nThe root element only:\n\n";
echo $doc->saveXML($doc->documentElement);

The output is as followed:

The whole doc:

<?xml version="1.0"?>
<root><child/></root>


The root element only:

<root><child/></root>

This probably should be already helpful for you. Additionally there is a constant for libxml which is said can be used to control whether or not the XML declaration is output. But I never used it:

LIBXML_NOXMLDECL (integer)

Drop the XML declaration when saving a document

Note: Only available in Libxml >= 2.6.21

From: http://php.net/libxml.constants

See the link for additional options, you might want to use the one or the other in the future.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM