获取xml文件以查找和替换文本。 PHP

时间:2019-01-25 12:43:55

标签: php xml xslt xml-parsing simplexml

我需要使用PHP代码更改XML文件中的文本。然后,我创建了以下代码:

1-获取文件

2-替换文字

3-用其他名称保存文件。

问题是我在替换xml文件中的某些文本时遇到了一些问题。

我可以替换简单字符串,但不能用'<'这样的字符替换文本。在真实的代码和文件下面。

原始XML路径:http://www.csainmobiliaria.com/imagenes/fotos/pisos-NOK.xml

1)此代码仅将文本Inmuebles更改为xxxxxxxx这很好

    $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)现在,如果我使用此代码将文本<Table Name="Inmuebles">更改为<xxxxxxxx> ,则会收到错误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)同样,如果我使用此代码删除文本Publicacion,则我收到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');

这是我需要获得的最终结果:http://www.csainmobiliaria.com/imagenes/fotos/pisos-OK.xml

捕获:enter image description here

3 个答案:

答案 0 :(得分:4)

您可以复制必要的节点,而不是删除任何多余的元素。例如,您可以使用帮助SimpleXML复制Inmuebles节点:

$path = 'http://www.csainmobiliaria.com/imagenes/fotos/pisos-NOK.xml';
$content = file_get_contents($path);
$sourceXML = new SimpleXMLElement($content);

$targetXML = new SimpleXMLElement("<Inmuebles></Inmuebles>");

$items = $sourceXML->xpath('Table[@Name=\'Inmuebles\']');
foreach ($items as $item) {
    foreach ($item->Inmueble as $inmueble) {
        $node  = $targetXML->addChild('Inmueble');
        $node->addChild('IdInmobiliariaExterna', $inmueble->IdInmobiliariaExterna);
        $node->addChild('IdPisoExterno', $inmueble->IdPisoExterno);
        $node->addChild('FechaHoraModificado', $inmueble->FechaHoraModificado);
        $node->addChild('TipoInmueble', $inmueble->TipoInmueble);
        $node->addChild('TipoOperacion', $inmueble->TipoOperacion);
    }
}

echo $targetXML->asXML()

此外,正如@ThW在评论中所说,您可以使用XLST,例如:

$path = 'http://www.csainmobiliaria.com/imagenes/fotos/pisos-NOK.xml';
$content = file_get_contents($path);
$sourceXML = new SimpleXMLElement($content);

$xslt='<?xml version="1.0" encoding="ISO-8859-1"?>
         <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
         <xsl:output method="xml" indent="yes"/>

         <xsl:template match="Table[@Name=\'Inmuebles\']">
             <Inmuebles>
                 <xsl:copy-of select="node()"/>
             </Inmuebles>
         </xsl:template>

         <xsl:template match="Table[@Name=\'Agencias\']"/>
</xsl:stylesheet>';


$xsl = new SimpleXMLElement($xslt);

$processor = new XSLTProcessor;
$processor->importStyleSheet($xsl);
$result = $processor->transformToXML($sourceXML);
$targetXML = new SimpleXMLElement($result);
echo $targetXML->asXML();

答案 1 :(得分:4)

DOMDocument允许您复制节点的结构,因此您不必复制所有细节(当规格更改时可能会丢失数据),而是可以复制整个节点(例如{ {1}}使用importNode()从一个文档到另一个文档,该文档具有一个参数,指示应复制元素的全部内容。这种方法还允许您使用相同的功能复制任何表,而无需更改代码...

<Inmueble>

如果希望进一步处理,可以更改将文档返回为DOMDocument或SimpleXML版本的方法。

对于SimpleXML,将返回值更改为...

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");

然后您可以将其称为...

return simplexml_import_dom($newRoot);

或者,如果您只想要固定的方法,则可以删除XPath并使用$ret = extractData ($xml_external_path, "Inmuebles"); echo $ret->asXML(); 查找要复制的节点...

getElementsByTagName()

要添加保存文件名,我向该函数添加了一个新参数,该新函数根本不返回任何内容-它仅加载文件并将结果保存为新文件名... < / p>

$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();

答案 2 :(得分:0)

再次考虑XSLT,这是一种符合W3C标准的专用语言,旨在根据要求的用户规范(例如1-3号需求)修改XML文件。与其他流行的声明性语言SQL一样,XSLT不仅限于PHP,还可以移植到其他应用程序层(Java,C#,Python,Perl,R)和专用的XSLT 1.0, 2.0, and 3.0 .exe processors

使用这种方法,XSLT的递归样式使您可以避免在应用程序层进行任何foreach循环,if逻辑以及诸如addChildappendChild的重复行。

XSLT (另存为.xsl文件,特殊的.xml文件或嵌入式字符串;可移植到PHP以外的其他接口上)

<?xml version="1.0"?>
 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     <xsl:output method="xml" indent="yes" encoding="ISO-8859-1"/>
     <xsl:strip-space elements="*"/>

     <!-- WALK DOWN TREE FROM ROOT -->
     <xsl:template match="Publication">
        <xsl:apply-templates select="Table"/>
     </xsl:template>

     <xsl:template match="Table[@Name='Inmuebles']">
         <Inmuebles>
             <xsl:apply-templates select="*"/>
         </Inmuebles>
     </xsl:template>

     <!-- EMPTY TEMPLATE TO REMOVE SPECIFIED NODES -->
     <xsl:template match="Table[@Name='Agencias']"/>

     <!-- RETURN ONLY FIRST FIVE NODES -->
     <xsl:template match="Table/*">
         <Inmuebles>
             <xsl:copy-of select="*[position() &lt;= 5]"/>
         </Inmuebles>
     </xsl:template>

</xsl:stylesheet>

XSLT Demo

PHP (使用php_xsl库)

// LOAD XML SOURCE
$url = 'http://www.csainmobiliaria.com/imagenes/fotos/pisos-NOK.xml';
$web_data = file_get_contents($url);
$xml = new SimpleXMLElement($web_data);

// LOAD XSL SCRIPT
$xsl = simplexml_load_file('/path/to/script.xsl');

// XSLT TRANSFORMATION
$proc = new XSLTProcessor;
$proc->importStyleSheet($xsl); 
$newXML = $proc->transformToXML($xml);

// OUTPUT TO CONSOLE
echo $newXML;

// SAVE TO FILE
file_put_contents('Output.xml', $newXML);

作为出色的XSLT专家@Dimitre Novatchev,通常会结束他的帖子:产生了所需的正确结果

<?xml version="1.0" encoding="ISO-8859-1"?>
<Inmuebles>
   <Inmuebles>
      <IdInmobiliariaExterna>B45695855</IdInmobiliariaExterna>
      <IdPisoExterno>100002</IdPisoExterno>
      <FechaHoraModificado>30/11/2018</FechaHoraModificado>
      <TipoInmueble>PISO</TipoInmueble>
      <TipoOperacion>3</TipoOperacion>
   </Inmuebles>
   <Inmuebles>
      <IdInmobiliariaExterna>B45695855</IdInmobiliariaExterna>
      <IdPisoExterno>100003</IdPisoExterno>
      <FechaHoraModificado>30/11/2018</FechaHoraModificado>
      <TipoInmueble>CHALET</TipoInmueble>
      <TipoOperacion>4</TipoOperacion>
   </Inmuebles>
</Inmuebles>