Home > Mobile >  SimpleXML root node prefix php with default namespace declaration
SimpleXML root node prefix php with default namespace declaration

Time:12-14

I'm creating an xml file with PHP. The file I need to create is this one I show you:

<p:FatturaElettronica versione="FPA12" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:p="http://microsoft.com/wsdl/types/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" versione="FPA12" >
 <FatturaElettronicaHeader>
  <DatiTrasmissione>
   <IdTrasmittente>
    <IdPaese>IT</IdPaese>
    <IdCodice>01234567890</IdCodice>
   </IdTrasmittente>
   <ProgressivoInvio>00001</ProgressivoInvio>
   <FormatoTrasmissione>FPA12</FormatoTrasmissione>
   <CodiceDestinatario>AAAAAA</CodiceDestinatario>
  </DatiTrasmissione>
  </FatturaElettronicaHeader>
<p:FatturaElettronica>

This is my code:

$xml = new SimpleXMLElement('<p:FatturazioneElettronica xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:p="http://microsoft.com/wsdl/types/" />');
$xml->addAttribute("versione","FPA12");
$xml->addAttribute("xmlns:xmlns:xsi","http://www.w3.org/2001/XMLSchema-instance");
$FatturaElettronicaHeader = $xml->addChild('FatturaElettronicaHeader');
$DatiTrasmissione=$FatturaElettronicaHeader->addChild('DatiTrasmissione');
$IdTrasmittente=$DatiTrasmissione->addChild('IdTrasmittente');
$IdTrasmittente->addChild('IdPaese', 'IT');
$IdTrasmittente->addChild('IdCodice','01234567890');

$ProgressivoInvio=$DatiTrasmissione->addChild('ProgressivoInvio', '00001');
$FormatoTrasmissione=$DatiTrasmissione->addChild('DatiTrasmissione', 'FPA12');
$CodiceDestinatario=$DatiTrasmissione->addChild('CodiceDestinatario', 'AAAAAA');

Because in my created file I initially had the prefix p: in each tag, as shown below

<p:FatturazioneElettronica xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:p="http://microsoft.com/wsdl/types/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" versione="FPA12">
 <p:FatturaElettronicaHeader>
   <p:DatiTrasmissione>
    <p:IdTrasmittente>
     <p:IdPaese>IT</p:IdPaese>
     <p:IdCodice>01234567890</p:IdCodice>
    </p:IdTrasmittente>
    <p:ProgressivoInvio>00001</p:ProgressivoInvio>
   <p:DatiTrasmissione>FPA12</p:DatiTrasmissione>
   <p:CodiceDestinatario>AAAAAA</p:CodiceDestinatario>
 </p:DatiTrasmissione>

while this prefix p: must be only in the root node (p:FatturaElettronica) I added xmlns="http://dummy.com"

<p:FatturazioneElettronica xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:p="http://microsoft.com/wsdl/types/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" versione="FPA12" xmlns="http://dummy.com">

and

$fatturaelettronicaheader = $xml->addChild('FatturaElettronicaHeader', '', 'http://dummy.com');

as it was suggested in this question

Only this 'http://dummy.com' is not present in the original xml file.

How can I solve this problem or possibly eliminate it before actually generating the file?

CodePudding user response:

First, your desired xml (as well as the one in the question you link to) is not well formed for several reasons.

Second, even after that's fixed (see below), it's not clear to me why you're going about it the way you do.

How about this way:

$string = '<?xml version="1.0" encoding="UTF-8"?>
<root>
   <p:FatturaElettronica xmlns:p="http://microsoft.com/wsdl/types/" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" versione="FPA12">
      <FatturaElettronicaHeader>
         <DatiTrasmissione>
            <IdTrasmittente>
               <IdPaese>IT</IdPaese>
               <IdCodice>01234567890</IdCodice>
            </IdTrasmittente>
            <ProgressivoInvio>00001</ProgressivoInvio>
            <FormatoTrasmissione>FPA12</FormatoTrasmissione>
            <CodiceDestinatario>AAAAAA</CodiceDestinatario>
         </DatiTrasmissione>
      </FatturaElettronicaHeader>
   </p:FatturaElettronica>
</root>';                                                                       
$xml = simplexml_load_string($string);

echo $xml->asXML() ."\r\n";

That should echo your well-formed xml.

CodePudding user response:

SimpleXML abstracts nodes and has some automatic logic for namespaces. That works fine for basic/simple XML structures.

For more complex XML structures you want to be explicit - so use DOM. It has specific methods for different node types with and without namespaces.

// define a list with the used namespaces
$namespaces = [
  'xmlns' => 'http://www.w3.org/2000/xmlns/',
  'xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
  'signature' => 'http://www.w3.org/2000/09/xmldsig#',
  'wsdl-types' => 'http://microsoft.com/wsdl/types/'
];

$document = new DOMDocument('1.0', 'UTF-8');
// create and append an element with a namespace
// this will add the namespace definition for the prefix "p" also
$document->appendChild(
    $root = $document->createElementNS($namespaces['wsdl-types'], 'p:FatturazioneElettronica')
);
// set an attribute without a namespace
$root->setAttribute('versione', 'FPA12');
// add namespace definitions using the reserved "xmlns" namespace
$root->setAttributeNS($namespaces['xmlns'], 'xmlns:xsi', $namespaces['xsi']);
$root->setAttributeNS($namespaces['xmlns'], 'xmlns:ds', $namespaces['signature']);

// create and append the an element - keep in variable for manipulation
// the element does not have a namespace
$root->appendChild(
    $header = $document->createElement('FatturaElettronicaHeader')    
);
$header->appendChild(
    $dati = $document->createElement('DatiTrasmissione')
);

$dati->appendChild(
    $id = $document->createElement('IdTrasmittente')
);

// create and append element, set text content using a chained call 
$id
    ->appendChild($document->createElement('IdPaese'))
    ->textContent = 'IT';
$id
    ->appendChild($document->createElement('IdCodice'))
    ->textContent = '01234567890';
  
$dati
    ->appendChild($document->createElement('ProgressivoInvio'))
    ->textContent = '00001';
$dati
    ->appendChild($document->createElement('FormatoTrasmissione'))
    ->textContent = 'FPA12';
$dati
    ->appendChild($document->createElement('CodiceDestinatario'))
    ->textContent = 'AAAAAA';

$document->formatOutput = TRUE;
echo $document->saveXML();

Output:

<?xml version="1.0" encoding="UTF-8"?>
<p:FatturazioneElettronica xmlns:p="http://microsoft.com/wsdl/types/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" versione="FPA12">
  <FatturaElettronicaHeader>
    <DatiTrasmissione>
      <IdTrasmittente>
        <IdPaese>IT</IdPaese>
        <IdCodice>01234567890</IdCodice>
      </IdTrasmittente>
      <ProgressivoInvio>00001</ProgressivoInvio>
      <FormatoTrasmissione>FPA12</FormatoTrasmissione>
      <CodiceDestinatario>AAAAAA</CodiceDestinatario>
    </DatiTrasmissione>
  </FatturaElettronicaHeader>
</p:FatturazioneElettronica>

Be aware that in your XML p:FatturazioneElettronica has a namespace. It resolves to {http://microsoft.com/wsdl/types/}FatturazioneElettronica. However I don't think that FatturazioneElettronica is a valid element in the WSDL types namespace.

FatturaElettronicaHeader (and the descandant nodes) do not have a namespace.

  • Related