Remove Namespace from Xml Using PHP

Remove namespace from XML using PHP

If you're using XPath then it's a limitation with XPath and not PHP look at this explanation on xpath and default namespaces for more info.

More specifically its the xmlns="" attribute in the root node which is causing the problem. This means that you'll need to register the namespace then use a QName thereafter to refer to elements.

$feed = simplexml_load_file('http://www.sitepoint.com/recent.rdf');
$feed->registerXPathNamespace("a", "http://www.domain.com/schema/data");
$result = $feed->xpath("a:Data/a:Something/...");

Important: The URI used in the registerXPathNamespace call must be identical to the one that is used in the actual XML file.

How to remove namespace with PHP SimpleXMLElement?

You can use 3rd parameter with blank value for addChild method. $xml->addChild('ItPrice', '1337', '');

$xml = new SimpleXMLElement('<yq1:ZwsCreteMaterialFrRef xmlns:yq1="urn:test-com:document:test:soap:functions:mc-style"></yq1:ZwsCreteMaterialFrRef>');
$namespaces = $xml->getDocNamespaces();
$xml->addChild('ItPrice', '1337', '');
echo $xml->asXml();

Remove Namespace from child Element XML PHP

SimpleXMLElement::addChild needs the namespace (if not the default one) in its third parameter.

If the namespace is not yet registered, it will be added. This is what you see in your result.

However you want to add a child element in a specific, existing namespace, namely http://base.google.com/ns/1.0 (it looks like an URL, however in terms of XML it is just a string).

Example:

$namespace = 'http://base.google.com/ns/1.0';
$root->channel->item->addChild('id', '456', $namespace);
# adds child <g:id>456</g:id>

This is what you want: Add the id element in the http://base.google.com/ns/1.0 namespace.

Here the namespace is abbreviated with g, the so called prefix (g:...). You can imagine the element name is {http://base.google.com/ns/1.0}id ("Clark notation").

See the first (root/document) element there you can see which prefix stands for which namespace:

<rss xmlns:g="http://base.google.com/ns/1.0"
xmlns:c="http://base.google.com/cns/1.0" version="2.0">

This is why by only using id for the element name when adding and telling the correct namespace, it is inserted with the g prefix.

However when you explicitly specify the prefix in the name adding the child element and providing a (new) namespace, the namespace for that elements' prefix will be with the added child because you told SimpleXML to do so (in your case by chance/error not intend, but that is just for explanation what happened).

<g:id xmlns:g="id">123</g:id>
  • Element name is id; with prefix: g:id; with namespace: {id}id
  • Namespace is id
  • Prefix in this (and all its child elements) for it is g

This is why you need to know the namespace of the child element you add and therefore you need to know the (long) namespace name: http://base.google.com/ns/1.0.

To find it, look up to the element that has the xmlns:<prefix> attribute, then see the value:

<rss xmlns:g="http://base.google.com/ns/1.0" ...>
^ \___________________________/
| namespace
prefix g is ---/

When you call addChild() with that namespace, an existing prefix (here: g) will be automatically chosen by SimpleXML.

But if that child element is the first element with that (new to the document) namespace, it will be added as in your case with the xmlns attribute (all attributes starting with xml (case insensitive) are reserved attribute names in XML, same for element names):

<g:price xmlns:g="price">0.00</g:price>

Prefix "g" is namespace "price" for that "price" element (and all its children if there would be any until another child element redefines the namespace of the prefix).

If you're now explicitly looking (in code) for what namespace which prefix is, you can obtain an associative array by calling SimpleXMLElement::getNamespaces:

$namespace = $root->getNamespaces(true)['g'];

However using the real namespace name is much better as the prefix can by anything and may change while the namespace name remains stable. Also its less code to write:

$namespace = 'http://base.google.com/ns/1.0';
$root->channel->item->addChild('id', '456', $namespace);

How to remove all namespaces from XML in PHP (tags and attributes)

To rewrite a complete XML document like renaming element or attribute names as well as changing namespace related data like xmlns attributes, you can use the expat based xml parser extension:

  • PHP XML Parser

This works by parsing the file and change the output on the fly. The parser invokes callback functions (so called handler) that gets the data pre-parsed, for example the elements name in form of a string and the attributes in form of an array.

You then can change these values on the fly and output the (potentially changed) data.

Done this way you don't need to care about regular expressions any longer (which is non-trivial for proper XML parsing).

You can find some boilerplate code to get this started in a previous answer of mine.

PHP/SOAP - Remove all namespaces BUT first

Consider XSLT, the special-purpose language designed to transform XML files and manipulating namespaces are among its regular uses. PHP can run XSLT 1.0 scripts using its php-xsl class. With this approach no array builds, foreach loops, if logic, or recursive function are needed.

XSLT (save as .xsl file, a special .xml file)

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>

<!-- IDENTITY TRANSFROM: COPY DOC AS IS -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>

<!-- REMOVE NAMESPACE PREFIXES -->
<xsl:template match="*[local-name()!='Contract']">
<xsl:element name="{local-name()}">
<xsl:apply-templates select="@*|node()"/>
</xsl:element>
</xsl:template>

</xsl:stylesheet>

Input XML (assuming below replicates OP's return)

<?xml version="1.0" encoding="UTF-8"?>
<sof:Contract xmlns:s="http://www.fines.pl/simple" xmlns:sof="http://www.fines.pl/sof" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.fines.pl/sof model.xsd ">
<sof:product>
<sof:prefix>MOP</sof:prefix>
</sof:product>
<sof:participants>
<sof:customers>
<sof:main_borrower>
<sof:personal_data>
<sof:pesel></sof:pesel>
<sof:firstname></sof:firstname>
<sof:lastname></sof:lastname>
<sof:firstname_father></sof:firstname_father>
<sof:firstname_mother></sof:firstname_mother>
<sof:secondname />
<sof:sex>female</sof:sex>
</sof:personal_data>
<sof:contact_data>
<sof:addresses>
<sof:address>
<sof:type>registered</sof:type>
<sof:street_name></sof:street_name>
<sof:block_number></sof:block_number>
<sof:flat_number></sof:flat_number>
<sof:postal_code></sof:postal_code>
<sof:city></sof:city>
</sof:address>
</sof:addresses>
<sof:phones_mobile>
<sof:phone_mobile>
<sof:type>personal</sof:type>
<sof:number>602200300</sof:number>
</sof:phone_mobile>
</sof:phones_mobile>
</sof:contact_data>
<sof:incomes>
<sof:income>
<sof:type>employment</sof:type>
<sof:main_income>true</sof:main_income>
<sof:fixed_term_contract>false</sof:fixed_term_contract>
<sof:paychecks>
<sof:paycheck>
<sof:amount_net>
<sof:amount>1444.00</sof:amount>
<sof:currency>PLN</sof:currency>
</sof:amount_net>
<sof:type>base</sof:type>
</sof:paycheck>
</sof:paychecks>
</sof:income>
</sof:incomes>
<sof:household_pointer>/households.0</sof:household_pointer>
</sof:main_borrower>
</sof:customers>
</sof:participants>
</sof:Contract>

PHP

// LOAD XML AND XSLT 
$doc = new DOMDocument();
$doc->load('Input.xml');

$xsl = new DOMDocument;
$xsl->load('XSLTScript.xsl');

// CONFIGURE TRANSFORMER
$proc = new XSLTProcessor;
$proc->importStyleSheet($xsl);

// RUN TRANSFORMATION
$newXML = $proc->transformToXML($doc);

// ECHO TO CONSOLE
echo $newXML;

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

Output XML (prefixes removed for all but the root)

<?xml version="1.0" encoding="utf-8"?>
<sof:Contract xsi:schemaLocation="http://www.fines.pl/sof model.xsd " xmlns:sof="http://www.fines.pl/sof" xmlns:s="http://www.fines.pl/simple" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<product>
<prefix>MOP</prefix>
</product>
<participants>
<customers>
<main_borrower>
<personal_data>
<pesel />
<firstname />
<lastname />
<firstname_father />
<firstname_mother />
<secondname />
<sex>female</sex>
</personal_data>
<contact_data>
<addresses>
<address>
<type>registered</type>
<street_name />
<block_number />
<flat_number />
<postal_code />
<city />
</address>
</addresses>
<phones_mobile>
<phone_mobile>
<type>personal</type>
<number>602200300</number>
</phone_mobile>
</phones_mobile>
</contact_data>
<incomes>
<income>
<type>employment</type>
<main_income>true</main_income>
<fixed_term_contract>false</fixed_term_contract>
<paychecks>
<paycheck>
<amount_net>
<amount>1444.00</amount>
<currency>PLN</currency>
</amount_net>
<type>base</type>
</paycheck>
</paychecks>
</income>
</incomes>
<household_pointer>/households.0</household_pointer>
</main_borrower>
</customers>
</participants>
</sof:Contract>

How to remove namespace from HTML content in XML file

I must have glossed over this in the documentation.

It took a little while to find, but the following seems to work well:

$content = $xpath->query('a:content/h:*', $context);
foreach ($content as $piece)
{
$piece->removeAttributeNS('http://www.w3.org/1999/xhtml', 'h');
$html_content .= $dom->saveXML($piece);
}

Hope this helps someone else trying to solve the same issue.

remove Name-Space from xml file and save as new XML

first create on simple php file to load xml From the URL:-

<?php
$dom = new DOMDocument();
$dom->load('http://services.gisgraphy.com/geoloc/search?lat=22.298569900000000000&lng=70.794301799999970000&radius=7000', true);
$dom->save('filename.xml');
?>

then create one XSLT file:-

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"><xsl:output method="xml" version="1.0" encoding="UTF-8" />
<xsl:template match="*">
<xsl:element name="{local-name()}">
<xsl:apply-templates select="@* | node()"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>

and create one php file to load xml file and implement our xslt file:-

<?php
$sourcedoc->load('filename.xml');
$stylesheet = new DOMDocument();
$stylesheet->load('new4convert.xsl');
// create a new XSLT processor and load the stylesheet
$xsltprocessor = new XSLTProcessor();
$xsltprocessor->importStylesheet($stylesheet);

// save the new xml file
file_put_contents('filename.xml', $xsltprocessor->transformToXML($sourcedoc));
?>

final total code if you want to all in one PHP file:-

<?php
$dom = new DOMDocument();
$dom->load('http://services.gisgraphy.com/geoloc/search?lat=22.298569900000000000&lng=70.794301799999970000&radius=7000', true);
$dom->save('filename.xml');
$sourcedoc = new DOMDocument();
$sourcedoc->load('filename.xml');
$stylesheet = new DOMDocument();
$stylesheet->load('new4convert.xsl');
// create a new XSLT processor and load the stylesheet
$xsltprocessor = new XSLTProcessor();
$xsltprocessor->importStylesheet($stylesheet);

// save the new xml file
file_put_contents('filename.xml', $xsltprocessor->transformToXML($sourcedoc));
?>


Related Topics



Leave a reply



Submit