我需要使用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
答案 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
逻辑以及诸如addChild
或appendChild
的重复行。
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() <= 5]"/>
</Inmuebles>
</xsl:template>
</xsl:stylesheet>
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>