I have a script in php which creates an XML file.
$xml1 = "<?xml version='1.0' encoding='utf-8'?>\n";
$xml1 .= "\t<invoices>\n";
$xml1 .= "\t\t<journal>\n";
I would need to add a schema link to "invoices" so that the XML output looks like the following:
<invoices xsi:noNamespaceSchemaLocation="http://schema.aptic.net/aptic-link-import-ledgeraccounts-v2.xsd">
Whatever I try I always receive an error and the XML file is not created. How could I solve this or where could I find information on how to insert the required schema link correctly.
What I have tried so far is to add the link with different solutions including ' or "
$xml1 .= "\t<invoices xsi:noNamespaceSchemaLocation="http://schema.aptic.net/aptic-link-import-ledgeraccounts-v2.xsd">\n";
$xml1 .= "\t<invoices 'xsi:noNamespaceSchemaLocation="http://schema.aptic.net/aptic-link-import-ledgeraccounts-v2.xsd"'>\n";
Thank you
ADDON
The following error comes up when opening the created file with your solution:
$xml1 .= "\t<invoices xsi:noNamespaceSchemaLocation=\"http://schema.aptic.net/aptic-link-import-ledgeraccounts-v2.xsd\">\n";
XML Parsing Error: prefix not bound to a namespace
<invoices xsi:noNamespaceSchemaLocation="http://schema.aptic.net/aptic-link-import-ledgeraccounts-v2.xsd">
--------^
SOLUTION:
The following code was the solution for me:
$xml1 = "<?xml version='1.0' encoding='utf-8'?>\n";
$xml1 .= "\t<invoices xmlns='http://www.w3schools.com' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xsi:noNamespaceSchemaLocation='http://schema.aptic.net/aptic-link-import-ledgeraccounts-v2.xsd'>\n";
$xml1 .= "\t\t<journal>\n";
Do not try to create xml's through string concatenation. You will have a hard time doing this. Use a designated php api for creating xml documents.
Here is a minimal example that will create a invoices.xml.
/* create a dom document with encoding utf8 */
$domtree = new DOMDocument('1.0', 'UTF-8');
/* create the root element of the xml tree */
$xmlRoot = $domtree->createElement("xml");
/* append it to the document created */
$xmlRoot = $domtree->appendChild($xmlRoot);
$invoices = $domtree->createElement("invoices");
$invoices->setAttribute('xsi:noNamespaceSchemaLocation', 'http://schema.aptic.net/aptic-link-import-ledgeraccounts-v2.xsd');
$invoices = $xmlRoot->appendChild($invoices);
$journal = $domtree->createElement("journal");
$journal = $invoices->appendChild($journal);
$domtree->save("invoices.xml");
Content will be:
<?xml version="1.0" encoding="UTF-8"?>
<xml><invoices xsi:noNamespaceSchemaLocation="http://schema.aptic.net/aptic-link-import-ledgeraccounts-v2.xsd"><journal/></invoices></xml>
Addon:
Based on your comment and post edit, I think you just need to quote the " in your string.
$xml1 .= "\t<invoices xsi:noNamespaceSchemaLocation=\"http://schema.aptic.net/aptic-link-import-ledgeraccounts-v2.xsd\">\n";
The attribute like xsi:noNamespaceSchemaLocation uses a namespace prefix. Because of the prefix a assume that it is the namespace http://www.w3.org/2001/XMLSchema-instance.
Namespaces need to be defined, but they will be defined as necessary if you use the namespace aware methods of the DOM API. The end with the suffix NS.
$document = new DOMDocument();
$document->appendChild(
$document->createElement('invoices')
);
$document->documentElement->setAttributeNS(
// namespace
'http://www.w3.org/2001/XMLSchema-instance',
// attribute name including namespace prefix
'xsi:noNamespaceSchemaLocation',
// attribute value
'http://schema.aptic.net/aptic-link-import-ledgeraccounts-v2.xsd'
);
$document->documentElement->appendChild(
$document->createElement('journal')
);
$document->formatOutput = TRUE;
Output:
<?xml version="1.0"?>
<invoices xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://schema.aptic.net/aptic-link-import-ledgeraccounts-v2.xsd">
<journal/>
</invoices>
You can see that the generated output includes a xmlns attribute that defines the nampespace used by the xsi prefix.
The XML view in the browsers hides the namespace definitions, often. Check the source to validate that it here.
You can generate the same XML uses string functions. If you do this keep in mind to escape values if needed.
Related
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?
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.
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.
I have an XML file with the root element name wwwjob. This root element contains attributes, I need to access the value of the 'method' attribute to be able to update various database entries.
This is a little bit of a learning curve at the moment.
<?xml version="1.0" encoding="iso-8859-1"?>
<wwwjob id="32cca11IACH" method="Delete">
some more xml stuff
</wwwjob>
Ive tried:
<?php $xml = $vacancyXML->wwwjob['method']; ?>
This just gave me 'NULL'.
Ive also tried:
<?php $xml = $vacancyXML->getName(); ?>
This just spits out the name 'wwwjob'.
I need to store the method (Delete/Update/Add) as a variable for use in later parts of the function.
Thanks
When loadinG to simplexml, attributes of the root element became attributes of the simpleXml object. So, you can get it just
$str = '<?xml version="1.0" encoding="iso-8859-1"?>
<wwwjob id="32cca11IACH" method="Delete">
</wwwjob>';
$vacancyXML = simplexml_load_string($str);
echo $vacancyXML['method']; // Delete
demo
You can get the attributes of the root element with SimpleXMLElement::attributes():
$www = new SimpleXMLElement($xml);
echo $www->attributes()->method; // Delete
Demo
I want to create dynamic tags in XML using PHP
like this : <wsse:Username>fqsuser01</wsse:Username>
the main thing is that I want the tags will change the value inside ---> "wsse"
(like this value)
what I need to do? to create this XML file wite PHP?
Thanks,
For this purpose you can use XMLWriter for example (another option is SimpleXML). Both option are in PHP core so any third party libraries aren't needed. wsse is a namespace - more about them you can read here
I also share with you some example code:
<?php
//create a new xmlwriter object
$xml = new XMLWriter();
//using memory for string output
$xml->openMemory();
//set the indentation to true (if false all the xml will be written on one line)
$xml->setIndent(true);
//create the document tag, you can specify the version and encoding here
$xml->startDocument();
//Create an element
$xml->startElement("root");
//Write to the element
$xml->writeElement("r1:id", "1");
$xml->writeElement("r2:id", "2");
$xml->writeElement("r3:id", "3");
$xml->endElement(); //End the element
//output the xml
echo $xml->outputMemory();
?>
Result:
<?xml version="1.0"?>
<root>
<r1:id>1</r1:id>
<r2:id>2</r2:id>
<r3:id>3</r3:id>
</root>
You could use a string and convert it to XML using simplexml_load_string(). The string must be well formed.
<?php
$usernames= array(
'username01',
'username02',
'username03'
);
$xml_string = '<wsse:Usernames>';
foreach($usernames as $username ){
$xml_string .= "<wsse:Username>$username</wsse:Username>";
}
$xml_string .= '</wsse:Usernames>';
$note=
<<<XML
$xml_string
XML; //backspace this line all the way to the left
$xml=simplexml_load_string($note);
?>
If you wanted to be able to change the namespaces on each XML element you would do something very similar to what is shown above. (Form a string with dynamic namespaces)
The XML portion that I instructed you to backspace all of the way has weird behavior. See https://www.w3schools.com/php/func_simplexml_load_string.asp for an example that you can copy & paste.
So, what i am trying to achieve is to load variables from PHP into an XML file.
this is how my XML looks at the moment:
<?xml version="1.0" encoding="ISO-8859-1"?>
<firstname></firstname>
<lastname></lastname>
And this is my PHP where i try to save the variables into the XML
$file = simplexml_load_file("filename.xml");
$xml->firstname = "Mark";
$xml->lastname = "Zuckerberg";
file_put_contents($file, $xml->asXML());
If i try to print this i get following error message:
Call to undefined method stdClass::asXML() in ... on line 1374
Any suggestions?
You don't create the initial XML file, the library you are using creates it for you.
XML DOM is a fine choice for this job.
$xml = new DOMDocument(); # Create a document
$xml_firstname = $xml->createElement("firstname", "Over"); # Create an element
$xml_lastname = $xml->createElement("lastname", "Coder"); # Create an element
$xml->appendChild($xml_firstname); # Add the element to the document
$xml->appendChild($xml_lastname); # Add the element to the document
$xml->save("myfancy.xml"); # Save the document to a file
The output would be
<?xml version="1.0" encoding="utf-8"?>
<firstname>Over</firstname>
<lastname>Coder</lastname>
Enable error reporting (like error_reporting( E_ALL );) and you will understand quickly why it does not work:
Warning: simplexml_load_file(): xml.xml:3: parser error : Extra content at the end of the document
// your XML is not correctly formatted (XML requires a root node)
Warning: Creating default object from empty value
// $xml->firstname when $xml does not exists
To resolve that, your XML should looks like this:
<?xml version="1.0" encoding="ISO-8859-1"?>
<data><!-- here comes the root node -->
<firstname></firstname>
<lastname></lastname>
</data>
And the PHP should looks like previous answers:
$xml = simplexml_load_file("filename.xml");
$xml->firstname = "Mark";
$xml->lastname = "Zuckerberg";
file_put_contents("filename_copy.xml", $xml->asXML());
First off: where do you establish $xml?
You start with $file = ... but then refer to the object as $xml.
Either change the object name to $xml or change the references to $file:
$xml = simplexml_load_file("filename.xml"); /* note the object name change */
$xml->firstname = "Mark";
$xml->lastname = "Zuckerberg";
Next, your file_put_contents() command is incorrect. The first parameter is accepts is the filename, however in your example $file is not a name but a simplexml object.
file_put_contents("path/to/file.xml", $xml->asXML());
Alternatively, use the asXML() method with the path by doing this (thanks bassxzero):
$xml->asXML("path/to/file.xml");
Finally, your script is outputting the error:
Call to undefined method stdClass::asXML()
This implies that you can't call $xml->axXML() as (I'm assuming) either the method doesn't exist, or the object doesn't have the correct method.
Changing the name of the object initially (the first issue) should fix this!
From the code, you load the XML into $file.
But you edit $xml. The below code should work
$xml = simplexml_load_file("filename.xml");
$xml->firstname = "Mark";
$xml->lastname = "Zuckerberg";
file_put_contents("output.xml", $xml->asXML());
I'm creating XML response for the one of our clients with the namespace URLs in that using PHP. I'm expecting the output as follows,
<?xml version="1.0" encoding="UTF-8"?>
<ns3:userResponse xmlns:ns3="http://www.w3.org/2001/XMLSchema-instance" xmlns:ns2="http://www.w3.org/2001/XMLSchema">
<Content>
<field1>fieldvalue1</field1>
</Content>
</ns3:userResponse>
But by using the following code,
<?php
// create a new XML document
$doc = new DomDocument('1.0', 'UTF-8');
// create root node
$root = $doc->createElementNS('http://www.w3.org/2001/XMLSchema-instance', 'ns3:userResponse');
$root = $doc->appendChild($root);
$root->setAttributeNS('http://www.w3.org/2001/XMLSchema-instance', 'ns1:schemaLocation','');
$root->setAttributeNS('http://www.w3.org/2001/XMLSchema', 'ns2:schemaLocation','');
// add node for each row
$occ = $doc->createElement('Content');
$occ = $root->appendChild($occ);
$child = $doc->createElement("field1");
$child = $occ->appendChild($child);
$value = $doc->createTextNode('fieldvalue1');
$value = $child->appendChild($value);
// get completed xml document
$xml_string = $doc->saveXML();
echo $xml_string;
DEMO:
The demo is here, http://codepad.org/11W9dLU9
Here the problem is, the third attribute is mandatory attribute for the setAttributeNS PHP function. So, i'm getting the output as,
<?xml version="1.0" encoding="UTF-8"?>
<ns3:userResponse xmlns:ns3="http://www.w3.org/2001/XMLSchema-instance" xmlns:ns2="http://www.w3.org/2001/XMLSchema" ns3:schemaLocation="" ns2:schemaLocation="">
<Content>
<field1>fieldvalue1</field1>
</Content>
</ns3:userResponse>
So, is there anyway to remove that ns3:schemaLocation and ns2:schemaLocation which is coming with empty value? I googled a lot but couldn't able to find any useful answers.
Any idea on this would be so great. Please help.
You create this attributes:
$root->setAttributeNS('http://www.w3.org/2001/XMLSchema-instance', 'ns1:schemaLocation','');
$root->setAttributeNS('http://www.w3.org/2001/XMLSchema', 'ns2:schemaLocation','');
remove this lines and they will be removed.
If you want to add some xmlns without using it in code is:
$attr_ns = $doc->createAttributeNS( 'http://www.w3.org/2001/XMLSchema', 'ns2:attr' );
Read this comment: http://php.net/manual/pl/domdocument.createattributens.php#98210