Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get xml file to find and replace text. PHP

I need to change texts in a XML file using PHP code. Then I created a code to:

1- get the file

2- replace the texts

3- save the file with other name.

Problem is that I am having some issues to replace some text in a xml file.

I am able to replace simples strings but I can not replace text with characters like '<'. Below the real code and files.

Original XML path: http://www.csainmobiliaria.com/imagenes/fotos/pisos-NOK.xml

1) This code just changes the text Inmuebles to xxxxxxxx. This works fine

    $xml_external_path = 'http://www.csainmobiliaria.com/imagenes/fotos/pisos-NOK.xml';
$xml = file_get_contents($xml_external_path);

$response = strtr($xml, array(
    'Inmuebles' => 'xxxxxxxx'
));

$newXml = $response;

$newXml = simplexml_load_string( $newXml );
$newXml->asXml('/home/csainmobiliaria/www/pisos-NEW.xml');

2) Now, if I use this code to change the text <Table Name="Inmuebles"> to <xxxxxxxx> I get a ERROR 500.

    $xml_external_path = 'http://www.csainmobiliaria.com/imagenes/fotos/pisos-NOK.xml';
$xml = file_get_contents($xml_external_path);

$response = strtr($xml, array(
    '<Table Name="Inmuebles">' => '<xxxxxxxx>'
));

$newXml = $response;

$newXml = simplexml_load_string( $newXml );
$newXml->asXml('/home/csainmobiliaria/www/pisos-NEW.xml');

3) In the same way, if I use this code to remove the text Publicacion I get a ERROR 500.

    $xml_external_path = 'http://www.csainmobiliaria.com/imagenes/fotos/pisos-NOK.xml';
$xml = file_get_contents($xml_external_path);

$response = strtr($xml, array(
    '<Publicacion>' => ''
));

$newXml = $response;

$newXml = simplexml_load_string( $newXml );
$newXml->asXml('/home/csainmobiliaria/www/pisos-NEW.xml');

This is the final result I need to get:http://www.csainmobiliaria.com/imagenes/fotos/pisos-OK.xml

Capture: enter image description here

like image 642
JPashs Avatar asked Jan 27 '23 20:01

JPashs


1 Answers

DOMDocument allows you to copy structures of nodes, so rather than having to copy all the details individually (which can be prone to missing data when the specification changes), you can copy an entire node (such as <Inmueble>) from one document to another using importNode() which has a parameter to indicate that the full content of the element should be copied. This approach also allows you to copy any of the tables using the same function without code changes...

function extractData ( $sourceFile, $table )    {
    // Load source data
    $source = new DOMDocument();
    $source->load($sourceFile);
    $xp = new DOMXPath($source);

    // Create new data document
    $newFile = new DOMDocument();
    $newFile->formatOutput = true;
    // Create base element with the table name in new document
    $newRoot = $newFile->createElement($table);
    $newFile->appendChild($newRoot);

    // Find the records to copy
    $records = $xp->query('//Table[@Name="'.$table.'"]/*');
    foreach ( $records as $record ) {
        // Import the node to copy and append it to new document
        $newRoot->appendChild();
    }
    // Return the source of the XML
    return $newFile->saveXML();
}

echo extractData ($xml_external_path, "Inmuebles");

You could alter the method to return the document as DOMDocument or even a SimpleXML version if you wished to process it further.

For SimpleXML, change the return to...

return simplexml_import_dom($newRoot);

and then you can call it as...

$ret = extractData ($xml_external_path, "Inmuebles");
echo $ret->asXML();

Or if you just want a fixed way of doing this, you can remove the XPath and just use getElementsByTagName() to find the nodes to copy...

$source = new DOMDocument();
$source->load($xml_external_path);

$newFile = new DOMDocument();
$newRoot = $newFile->createElement("Inmuebles");
$newFile->appendChild($newRoot);

// Find the records to copy
foreach ( $source->getElementsByTagName("Inmueble") as $record ) {
    $newRoot->appendChild($newFile->importNode($record, true));
}
echo $newFile->saveXML();

To add the save file name, I've added a new parameter to the function, this new function doesn't return anything at all - it just loads the file and saves the result to the new file name...

function extractData ( $sourceFile, $table, $newFileName )    {
    // Load source data
    $source = new DOMDocument();
    $source->load($sourceFile);
    $xp = new DOMXPath($source);

    // Create new file document
    $newFile = new DOMDocument();
    $newFile->formatOutput = true;
    // Create base element with the table name in new document
    $newRoot = $newFile->createElement($table);
    $newFile->appendChild($newRoot);

    // Find the records to copy
    $records = $xp->query('//Table[@Name="'.$table.'"]/*');
    foreach ( $records as $record ) {
        // Import the node to copy and append it to new document
        $importNode = $newFile->importNode($record, true);
        // Add new content
        $importNode->appendChild($newFile->createElement("Title", "value"));
        $newRoot->appendChild();
    }

    // Update Foto elements
    $xp = new DOMXPath($newFile);
    $fotos = $xp->query("//*[starts-with(local-name(), 'Foto')]");
    foreach ( $fotos as $foto ) {
        $path = $foto->nodeValue;
        if( substr($path, 0, 5) == "/www/" )    {
            $path = substr($path,4);
        }
        // Replace node with new version
        $foto->parentNode->replaceChild($newFile->createElement("Foto1", $path), 
                  $foto);
    }  

    $newFile->save($newFileName);
}
$xml_external_path = 'http://www.csainmobiliaria.com/imagenes/fotos/pisos.xml';
$xml_external_savepath = 'saveFile.xml';

extractData ($xml_external_path, "Inmuebles", $xml_external_savepath);
like image 195
Nigel Ren Avatar answered Jan 30 '23 05:01

Nigel Ren