I need to delete elements of an XML file using PHP.
This is my XML file
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<GetVehiculesLocationResponse xmlns="http://google.fr/">
<GetVehiculesLocationResult>
<Location>
<idVH>001</idVH>
<date>2020-06-30T09:06:39</date>
<latitude>111111</latitude>
<longitude>11111</longitude>
</Location>
<Location>
<idVH>002</idVH>
<date>2020-04-02T13:45:51</date>
<latitude>1111111</latitude>
<longitude>111111</longitude>
</Location>
<Location>
<idVH>11111111</idVH>
<date>2020-03-24T21:49:46</date>
<latitude>1111111</latitude>
<longitude>11111111</longitude>
</Location>
</GetVehiculesLocationResult>
</GetVehiculesLocationResponse>
</soap:Body>
</soap:Envelope>
I want to delete elements (in this case Location) where idVH is a certain value (in this case 002)
I have tried this but it doesn't work
$xml1 = simplexml_load_string($result);
$items = $xml1->xpath("/soap:Envelope/soap:Body/GetVehiculesLocationResponse/GetVehiculesLocationResult/Location[idVH = 002]");
foreach ($items as $i) unset($i[0]);
echo $xml1->asXML();
The issue is that the element GetVehiculesLocationResponse defines a new default namespace, so that and the child elements are all in that new namespace...
<GetVehiculesLocationResponse xmlns="http://google.fr/">
So first register the new namespace and then use it as a prefix in the lower level elements...
$xml1->registerXPathNamespace("d", "http://google.fr/");
$items = $xml1->xpath("/soap:Envelope/soap:Body/d:GetVehiculesLocationResponse/d:GetVehiculesLocationResult/d:Location[d:idVH = '002']");
Consider XSLT (sibling to XPath), the special-purpose language designed to transform XML files and especially best suited for processing many elements. In fact, you can even pass parameters like 001 from PHP to XSLT. PHP can run XSLT 1.0 scripts with its xsl class using DOMDocument library.
XSLT
<?xml version="1.0" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:googl="http://google.fr/">
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- DEFINE PARAM WITH DEFAULT -->
<xsl:param name="id_param">001</xsl:param>
<!-- IDENTITY TRANSFORM -->
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
<!-- KEEP NODES BY PARAM VALUE -->
<xsl:template match="googl:GetVehiculesLocationResult">
<xsl:copy>
<xsl:copy-of select="googl:Location[googl:idVH != $id_param]"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
PHP (pass parameters to XSLT in loop)
// LOAD XML
$xml = new DOMDocument('1.0', 'UTF-8');
$xml->load($data->xmlFile);
// LOAD XSLT
$xsl = new DOMDocument('1.0', 'UTF-8');
$xsl->load('XSLT_Script.xsl');
// INITIALIZE TRANSFORMER
$proc = new XSLTProcessor;
$proc->importStyleSheet($xsl);
foreach($param as array('001', '002')) {
// SET PARAMETER VALUE
$proc->setParameter('', 'id_param', $param);
// TRANSFORM SOURCE
$xml = $proc->transformToDoc($xml);
}
// ECHO TO SCREEN
echo $xml->saveXML();
// SAVE TO FILE
file_put_contents($data->xmlFile, $xml);
Output
<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soap:Body>
<GetVehiculesLocationResponse xmlns="http://google.fr/">
<GetVehiculesLocationResult>
<Location>
<idVH>11111111</idVH>
<date>2020-03-24T21:49:46</date>
<latitude>1111111</latitude>
<longitude>11111111</longitude>
</Location>
</GetVehiculesLocationResult>
</GetVehiculesLocationResponse>
</soap:Body>
</soap:Envelope>
Online Demo
Related
I'm having some difficulties in changing XML Node values with PHP.
My XML is the following
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ProcessTransaction
xmlns="http://example.com">
<TransactionRequest
xmlns="http://example.com">
<Header>
<RequestType>SALE</RequestType>
<RequestMethod>SYNCHRONOUS</RequestMethod>
<MerchantInfo>
<PosName>kwstasna</PosName>
<PosID>1234</PosID>
</MerchantInfo>
</Header>
</TransactionRequest>
</ProcessTransaction>
</soap:Body>
</soap:Envelope>
And i want to change PosName and PosID.
The XML is received from a POST Request.
If i print_r($REQUEST['xml']
I get the values in text.
And what i've tried is the following
$posid = '321';
$posname = 'nakwsta';
$result = $xml->xpath("/soap:Envelope/soap:Body/ProcessTransaction/TransactionRequest/Header/MerchantInfo");
$result[0]->PosID = $posid;
$result[0]->PosName = $posname;
echo $result;
But i get an empty array Array[]
I think my mistake is in the values of <soap:Envelope for example.
Anyone that had the same issue and find out the way to solve it?
Thanks a lot for your time.
The ProcessTransaction element (and all of its child nodes) are in the "http://example.com" namespace. If you want to access them using xpath(), you'll need to register a namespace prefix:
$xml->registerXPathNamespace('ex', 'http://example.com');
You can then use the ex prefix on all relevant parts of your query
$result = $xml->xpath("/soap:Envelope/soap:Body/ex:ProcessTransaction/ex:TransactionRequest/ex:Header/ex:MerchantInfo");
The rest of your code should function correctly, see https://eval.in/916856
Consider a parameterized XSLT (not unlike parameterized SQL) where PHP passes value to the underlying script with setParameter().
As information, XSLT (sibling to XPath) is a special-purpose language designed to transform XML files. PHP can run XSLT 1.0 scripts with the XSL class. Specifically, below runs the Identity Transform to copy XML as is and then rewrites the PosName and PosID nodes. Default namespace is handled accordingly in top root tag aligned to doc prefix.
XSLT (save as .xsl file, a special well-formed .xml file)
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:doc="http://example.com">
<xsl:output method="xml" indent="yes" />
<xsl:strip-space elements="*" />
<xsl:param name="PosNameParam"/>
<xsl:param name="PosIDParam"/>
<!-- IDENTITY TRANSFORM -->
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<!-- RE-WRITE PosName NODE -->
<xsl:template match="doc:PosName">
<xsl:copy>
<xsl:value-of select="$PosNameParam"/>
</xsl:copy>
</xsl:template>
<!-- RE-WRITE PosID NODE -->
<xsl:template match="doc:PosID">
<xsl:copy>
<xsl:value-of select="$PosIDParam"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
PHP
$posid = '321';
$posname = 'nakwsta';
// Load XML and XSL
$xml = new DOMDocument;
$xml->load('Input.xml');
$xsl = new DOMDocument;
$xsl->load('XSLTScript.xsl');
// Configure transformer
$proc = new XSLTProcessor;
$proc->importStyleSheet($xsl);
// Assign values to XSLT parameters
$proc->setParameter('', 'PosNameParam', $posid);
$proc->setParameter('', 'PosIDParam', $posname);
// Transform XML source
$newXML = new DOMDocument;
$newXML = $proc->transformToXML($xml);
// Output to console
echo $newXML;
// Output to file
file_put_contents('Output.xml', $newXML);
Output
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ProcessTransaction xmlns="http://example.com">
<TransactionRequest>
<Header>
<RequestType>SALE</RequestType>
<RequestMethod>SYNCHRONOUS</RequestMethod>
<MerchantInfo>
<PosName>nakwsta</PosName>
<PosID>321</PosID>
</MerchantInfo>
</Header>
</TransactionRequest>
</ProcessTransaction>
</soap:Body>
</soap:Envelope>
I'm trying to separate an XML file into two files, longrentals.xml and shortrentals.xml but have hit a last hurdle I'm stuck on. The following is what I would like to happen:
rentals.xml is parsed and for each instance of term = "short" the top parent "property" node of that entry is saved to shortrentals.xml.
Each instance is removed from the rentals.xml file (after extracting).
The shortrentals.xml file is saved.
The remaining entries in the original file is saved to longrentals.xml.
The XML structure is as follows:
<property>
...
<rent>
<term>short</term>
<freq>week</freq>
<price_peak>5845</price_peak>
<price_high>5845</price_high>
<price_medium>4270</price_medium>
<price_low>3150</price_low>
</rent>
...
</property>
The code I'm using is as follows:
$destination = new DOMDocument;
$destination->preserveWhiteSpace = true;
$destination->loadXML('<?xml version="1.0" encoding="utf-8"?><root></root>');
$source = new DOMDocument;
$source->load('file/rentals.xml');
$xp = new DOMXPath($source);
$destRoot = $destination->getElementsByTagName("root")->item(0);
foreach ($xp->query('/root/property/rent[term = "short"]') as $item) {
$newItem = $destination->importNode($item, true);
$destRoot->appendChild($newItem);
$item->parentNode->removeChild($item);
}
$source->save("file/longrentals.xml");
$destination->formatOutput = true;
$destination->save("file/shortrentals.xml");
This works except the output in shortrentals.xml only contains the rent node not the top level parent Property node. Also the removed entry from longrentals.xml only removes the Rent child node. So, how do I go up a level using my code please?
You can use the parentNode attribute of a DOMNode to go up a level in the structure (similar to how you do it in the removeChild code)...
foreach ($xp->query('/root/property/rent[term = "short"]') as $item) {
$property = $item->parentNode;
$newItem = $destination->importNode($property, true);
$destRoot->appendChild($newItem);
$property->parentNode->removeChild($property);
}
Alternatively, consider XSLT, the special-purpose XML transformation language, to create both such XML files without foreach loops. Here, XSLT is embedded as string but can be parsed from file like any other XML file. Assumed XML structure: <root><property><rent>...
shortrentals.xml output
// Load XML and XSL sources
$xml = new DOMDocument;
$xml->load('file/rentals.xml');
$xslstr = '<?xml version="1.0" ?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/root">
<xsl:copy>
<xsl:apply-templates select="property[rent/term=\'short\']"/>
</xsl:copy>
</xsl:template>
<xsl:template match="property">
<xsl:copy>
<xsl:copy-of select="*"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>';
$xsl = new DOMDocument;
$xsl->loadXML($xslstr);
// Configure transformer
$proc = new XSLTProcessor;
$proc->importStyleSheet($xsl);
// Transform XML source
$newXML = new DOMDocument;
$newXML = $proc->transformToXML($xml);
// Output file
file_put_contents('file/shortrentals.xml', $newXML);
longrentals.xml (Using Identity Transform and empty template to remove nodes)
// Load XML and XSL sources
$xml = new DOMDocument;
$xml->load('file/rentals.xml');
$xslstr = '<?xml version="1.0" ?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- Identity Transform -->
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<!-- Remove Non-Short Terms -->
<xsl:template match="property[rent/term=\'short\']"/>
</xsl:stylesheet>';
$xsl = new DOMDocument;
$xsl->loadXML($xslstr);
// Configure transformer
$proc = new XSLTProcessor;
$proc->importStyleSheet($xsl);
// Transform XML source
$newXML = new DOMDocument;
$newXML = $proc->transformToXML($xml);
// Output file
file_put_contents('file/longrentals.xml', $newXML);
I have an XML file and has 300 elements. I just want to pull 10 latest records from it and create another XML file.
I will really appreciate if you can just give me some ideas about it?
PHP
$file = '/directory/xmlfile.xml';
if(!$xml = simplexml_load_file($file)){
exit('Failed to open '.$file);
} else{
print_r($xml);
// I want to do some logic here to retrieve top 10 records from file and then create another xml file with 10 records
}
XML Sample Data
<data>
<total>212</total>
<start>0</start>
<count>212</count>
<data>
<item0>
<id>123</id>
<title>abc-test1</title>
<clientContact>
<id>111</id>
<firstName>abc</firstName>
<lastName>xyz</lastName>
<email>abc#xyz.ca</email>
</clientContact>
<isOpen>1</isOpen>
<isPublic>1</isPublic>
<isJobcastPublished>1</isJobcastPublished>
<owner>
<id>222</id>
<firstName>testname</firstName>
<lastName>testlastname</lastName>
<address>
<address1>test address,</address1>
<address2>test</address2>
<city>City</city>
<state>state</state>
<zip>2222</zip>
<countryID>22</countryID>
<countryName>Country</countryName>
<countryCode>ABC</countryCode>
</address>
<email>test#test.com</email>
<customText1>test123</customText1>
<customText2>testxyz</customText2>
</owner>
<publicDescription>
<p>test info</p>
</publicDescription>
<status>test</status>
<dateLastModified>22222</dateLastModified>
<customText4>test1</customText4>
<customText10>test123</customText10>
<customText11>test</customText11>
<customText16>rtest</customText16>
<_score>123</_score>
</item0>
<item1>
...
</item1>
...
</data>
</data>
Consider XSLT, the special-purpose language designed to transform/manipulate XML to various end uses like extracting top ten <item*> tags. No need of foreach or if logic. PHP maintains an XSLT processor that can be enabled in .ini file (php-xsl).
Specifically, XSLT runs the Identity Transform to copy document as is then writes a blank template for item nodes with position over 10. XML was a bit difficult due to same parent/child <data> tags.
XSLT (save as .xsl file which is a well-formed xml)
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[substring(name(),1,4)='item' and position() > 10]"/>
</xsl:stylesheet>
PHP
$file = '/directory/xmlfile.xml';
if(!$xml = simplexml_load_file($file)) {
exit('Failed to open '.$file);
} else {
// Load XSLT
$xsl = new DOMDocument;
$xsl->load('/path/to/xsl_script.xsl');
// Configure transformer
$proc = new XSLTProcessor;
$proc->importStyleSheet($xsl);
// Transform XML source
$newXML = new DOMDocument;
$newXML = $proc->transformToXML($xml);
// Echo new XML tree
echo $newXML;
// Save output to file
$xmlfile = '/path/to/output.xml';
file_put_contents($xmlfile, $newXML);
}
I have to clone an XML node and its childs and append it to a new XML in a specifics tag.
Ie:
Source XML:
<root>
<element>
<back>
<item1>ABC</item1>
<item2>DEF</item2>
<more>
<moreitem>GHI</moreitem>
</more
</back>
</element>
</root>
Destination XML:
<root>
<base1>
<item1>FOO</item1>
<item2>BAR</item2>
<base2>
**<back>From source XML and all its childs here</back>**
</base2>
</base1>
<root>
DOMXpath::evaluate() allows you to fetch nodes using Xpath expressions. DOMDocument::importNode() duplicates a node and imports a node into a target document. DOMNode::cloneNode() create a duplicate of node to add in the same document. DOMNode::appendChild() allows you to append the imported/cloned node.
$source = <<<'XML'
<root>
<element>
<back>
<item1>ABC</item1>
<item2>DEF</item2>
<more>
<moreitem>GHI</moreitem>
</more>
</back>
</element>
</root>
XML;
$target = <<<'XML'
<root>
<base1>
<item1>FOO</item1>
<item2>BAR</item2>
<base2>
</base2>
</base1>
</root>
XML;
$sourceDocument = new DOMDocument();
$sourceDocument->loadXml($source);
$sourceXpath = new DOMXpath($sourceDocument);
$targetDocument = new DOMDocument();
$targetDocument->loadXml($target);
$targetXpath = new DOMXpath($targetDocument);
foreach ($targetXpath->evaluate('/root/base1/base2[1]') as $targetNode) {
foreach ($sourceXpath->evaluate('/root/element/back') as $backNode) {
$targetNode->appendChild($targetDocument->importNode($backNode, TRUE));
}
}
echo $targetDocument->saveXml();
Output:
<?xml version="1.0"?>
<root>
<base1>
<item1>FOO</item1>
<item2>BAR</item2>
<base2>
<back>
<item1>ABC</item1>
<item2>DEF</item2>
<more>
<moreitem>GHI</moreitem>
</more>
</back>
</base2>
</base1>
</root>
Of course you can use XSLT, the native programming language to restructure XML documents to any nuanced needs. Specifically here, you require pulling XML content from an external source XML file. And PHP like other general purpose languages (Java, C#, Python, VB) maintain libraries for XSLT processing.
XSLT (save as .xsl or .xslt file to be used in PHP below and be sure Source and Destination XML files are in same directory)
<?xml version="1.0" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output version="1.0" encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*" />
<!-- Identity Transform -->
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="back">
<back>
<xsl:copy-of select="document('Source.xml')"/>
</back>
</xsl:template>
</xsl:transform>
PHP (loading XML and XSL files externally but can be embedded as string)
$destinationdoc = new DOMDocument();
$doc1->load('Destination.xml');
$xsl = new DOMDocument;
$xsl->load('XSLTScript.xsl');
// Configure the transformer
$proc = new XSLTProcessor;
$proc->importStyleSheet($xsl);
// Transform XML source
$newXml = $proc->transformToXML($doc1);
// Save output to file
$xmlfile = 'FinalOutput.xml';
file_put_contents($xmlfile, $newXml);
OUTPUT (using your above posted Source and Destination xml)
<?xml version="1.0" encoding="UTF-8"?>
<root>
<base1>
<item1>FOO</item1>
<item2>BAR</item2>
<base2>
<back>
<root>
<element>
<back>
<item1>ABC</item1>
<item2>DEF</item2>
<more>
<moreitem>GHI</moreitem>
</more>
</back>
</element>
</root>
</back>
</base2>
</base1>
</root>
This is an easy way to do this:
$src = new DOMDocument();
$dst = new DOMDocument();
$src->loadXML($src_xml);
$dst->loadXML($dst_xml);
$back = $src->getElementsByTagName('back')->item(0);
$base = $dst->getElementsByTagName('base2')->item(0);
$base->appendChild( $dst->importNode( $back, true ) );
echo $dst->saveXML();
I have one field $xml that contains some XML value. First I must mention that elements are not seperated each in new line (row) but they are bounded together like a String without new lines.
I will first display XML structure how it looks to be easily "readable".
<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope xmlns:soapenv=" http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<p:queryBillingAccountResponse xmlns:p=" http://www.ibm.com">
<ns0:customerAccount xmlns:ns0=" http://www.ibm.com/xmlns/">
<AccountStatus>Paid</AccountStatus>
<ComponentCustomerAccount>
<Name>ADSL 4</Name>
<CharacteristicValue>
<Characteristic>
<Name>Balance</Name>
</Characteristic>
<Value>0.0</Value>
</CharacteristicValue>
<AccountStatus>Paid</AccountStatus>
</ComponentCustomerAccount>
</ns0:customerAccount>
</p:queryBillingAccountResponse>
</soapenv:Body>
</soapenv:Envelope>
<AccountStatus>Paid</AccountStatus>
</ComponentCustomerAccount>
</ns0:customerAccount>
</p:queryBillingAccountResponse>
</soapenv:Body>
</soapenv:Envelope>
but I again I must mention that real value in $xml field is not so easily readable.
On example it looks like this
<?xml version="1.0" encoding="utf-8"?><soapenv:Envelope xmlns:soapenv=" http://schemas.xmlsoap.org/soap/envelope/"><soapenv:Body><p:queryBillingAccountResponse xmlns:p=" http://www.ibm.com">.......
I want to delete elements : ?xmlversion soapenv:Envelope and soapenv:Body along with their attributes. I want to delete them on the beggining and on the end of xml value. Everything else stays as it is1 How to achive this? So my new value in php field should start from queryBillingAccountResponse element. thank you
For valid XML you can use SimpeXML or DOMDocument to query the child nodes of the body element.
$xml = '<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<p:queryBillingAccountResponse xmlns:p="http://www.ibm.com">
<ns0:customerAccount xmlns:ns0="http://www.ibm.com/xmlns/">
<AccountStatus>Paid</AccountStatus>
<ComponentCustomerAccount>
<Name>ADSL 4</Name>
<CharacteristicValue>
<Characteristic>
<Name>Balance</Name>
</Characteristic>
<Value>0.0</Value>
</CharacteristicValue>
<AccountStatus>Paid</AccountStatus>
</ComponentCustomerAccount>
</ns0:customerAccount>
</p:queryBillingAccountResponse>
</soapenv:Body>
</soapenv:Envelope>';
$xml = simplexml_load_string($xml);
$xml = $xml->xpath('//soapenv:Body/child::*')[0];
echo $xml->asXML();
The result is:
<p:queryBillingAccountResponse xmlns:p="http://www.ibm.com">
<ns0:customerAccount xmlns:ns0="http://www.ibm.com/xmlns/">
<AccountStatus>Paid</AccountStatus>
<ComponentCustomerAccount>
<Name>ADSL 4</Name>
<CharacteristicValue>
<Characteristic>
<Name>Balance</Name>
</Characteristic>
<Value>0.0</Value>
</CharacteristicValue>
<AccountStatus>Paid</AccountStatus>
</ComponentCustomerAccount>
</ns0:customerAccount>
</p:queryBillingAccountResponse>
But the problem is that your XML isn't valid and I don't know if it's a copy and paste error.
This is easiest and the most foolproof with XSLT:
function extract_body_stripns($xmlstring) {
static $xsl = NULL;
if ($xsl === NULL) {
$xsl_soap_body_nons = <<<'EOT'
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0"
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output encoding="UTF-8" method="xml" />
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[namespace-uri()]" priority="1">
<xsl:element name="{local-name()}">
<xsl:apply-templates select="#*|node()"/>
</xsl:element>
</xsl:template>
<xsl:template match="#*[namespace-uri()]" priority="1">
<xsl:attribute name="{local-name()}">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:template>
<xsl:template match="/">
<xsl:apply-templates select="/soapenv:Envelope/soapenv:Body/*"/>
</xsl:template>
</xsl:stylesheet>
EOT;
$style = new DOMDocument();
$style->loadXML($xsl_soap_body_nons, LIBXML_COMPACT | LIBXML_NOBLANKS | LIBXML_NONET);
$xsl = new XSLTProcessor();
$xsl->importStylesheet($style);
unset($style);
}
$d = new DOMDocument();
$d->loadXML($xmlstring, LIBXML_COMPACT | LIBXML_NONET);
$newd = $xsl->transformToDoc($d);
unset($d);
return $newd->saveXML($newd->documentElement);
}
Using this function:
echo extract_body_stripns($xmlString);
Result is:
<queryBillingAccountResponse>
<customerAccount>
<ComponentCustomerAccount>
<Name>ADSL 4</Name>
<CharacteristicValue>
<Characteristic>
<Name>Balance</Name>
</Characteristic>
<Value>0.0</Value>
</CharacteristicValue>
<AccountStatus>Paid</AccountStatus>
</ComponentCustomerAccount>
</customerAccount>
</queryBillingAccountResponse>
Note that if you ever have namespaced attributes in your source document, the process of stripping namespaces may cause you to lose some of them. E.g. with the element <myelement ns:myattrib="a" myattrib="b"/>, one of your attributes will be lost, and which one you will lose is not consistent!
You can use ereg_replace
http://php.net/manual/en/function.ereg-replace.php
Using regex to identify elements you want to delete.