获取 xml 文件以查找和替换文本。 PHP
Get xml file to find and replace text. PHP
我需要使用 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
,我会收到错误 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
捕获:
您可以复制必要的节点而不是删除任何多余的元素。例如,您可以使用 help 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();
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()
其中有一个参数表示应该复制元素的全部内容。这种方法还允许您使用相同的函数复制任何表而无需更改代码...
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 文档作为 DOMDocument 或什至是 SimpleXML 版本,如果您希望进一步处理它的话。
对于 SimpleXML,将 return 更改为...
return simplexml_import_dom($newRoot);
然后你可以称它为...
$ret = extractData ($xml_external_path, "Inmuebles");
echo $ret->asXML();
或者,如果您只想以一种固定的方式执行此操作,您可以删除 XPath 并仅使用 getElementsByTagName()
查找要复制的节点...
$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();
为了添加保存文件名,我在函数中添加了一个新参数,这个新函数根本 return 什么都没有 - 它只是加载文件并将结果保存到新的文件名...
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);
再考虑一下,XSLT, the W3C standards compliant, special-purpose language designed to modify XML files to needed user specification such as your #1-3 needs. Like the other popular declarative language, SQL, XSLT is not limited to PHP but portable to other application layers (Java, C#, Python, Perl, R) and dedicated XSLT 1.0, 2.0, and 3.0 .exe processors。
通过这种方法,XSLT 的递归样式允许您避免任何 foreach
循环、if
逻辑,以及在应用程序中调用 addChild
或 appendChild
等重复行层.
XSLT (另存为 .xsl 文件、特殊的 .xml 文件或嵌入字符串;可移植到 [= 以外的其他界面43=])
<?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>
我需要使用 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
,我会收到错误 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
捕获:
您可以复制必要的节点而不是删除任何多余的元素。例如,您可以使用 help 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();
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()
其中有一个参数表示应该复制元素的全部内容。这种方法还允许您使用相同的函数复制任何表而无需更改代码...
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 文档作为 DOMDocument 或什至是 SimpleXML 版本,如果您希望进一步处理它的话。
对于 SimpleXML,将 return 更改为...
return simplexml_import_dom($newRoot);
然后你可以称它为...
$ret = extractData ($xml_external_path, "Inmuebles");
echo $ret->asXML();
或者,如果您只想以一种固定的方式执行此操作,您可以删除 XPath 并仅使用 getElementsByTagName()
查找要复制的节点...
$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();
为了添加保存文件名,我在函数中添加了一个新参数,这个新函数根本 return 什么都没有 - 它只是加载文件并将结果保存到新的文件名...
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);
再考虑一下,XSLT, the W3C standards compliant, special-purpose language designed to modify XML files to needed user specification such as your #1-3 needs. Like the other popular declarative language, SQL, XSLT is not limited to PHP but portable to other application layers (Java, C#, Python, Perl, R) and dedicated XSLT 1.0, 2.0, and 3.0 .exe processors。
通过这种方法,XSLT 的递归样式允许您避免任何 foreach
循环、if
逻辑,以及在应用程序中调用 addChild
或 appendChild
等重复行层.
XSLT (另存为 .xsl 文件、特殊的 .xml 文件或嵌入字符串;可移植到 [= 以外的其他界面43=])
<?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>