<?php
include "../music/php/logic/core.php";
include "../music/php/logic/settings.php";
include "../music/php/logic/music.php";
$top = "At world's end";
// create doctype
$dom = new DOMDocument("1.0");
header("Content-Type: text/xml");
?>
<music>
<?php $_xml = "<title>".$top."</title>";
echo $_xml; ?>
</music>
I'm using this code to generate a dynamic XML document. The file is saved as PHP.
My problem is that I can't echo php variables into the xml. However I can echo "literal" type text. I can't see anything wrong with my approach, it just doesn't work!
I'm pretty new to XML so I've probably missed something glaringly simple.
I've also tried lines like:
<title><?php echo $top; ?></title>
You don't use DOM this way. You use the DOM API to create the entire document:
$doc = new DOMDocument();
$books = $doc->createElement( "books" );
$doc->appendChild( $books );
// ...
See:
http://www.ibm.com/developerworks/library/os-xmldomphp/
http://www.tonymarston.net/php-mysql/dom.html
https://web.archive.org/web/1/http://articles.techrepublic%2ecom%2ecom/5100-10878_11-6141415.html
A more verbose example (generating XHTML with DOM)
// Create head element
$head = $document->createElement('head');
$metahttp = $document->createElement('meta');
$metahttp->setAttribute('http-equiv', 'Content-Type');
$metahttp->setAttribute('content', 'text/html; charset=utf-8');
$head->appendChild($metahttp);
See this tutorial on how to use DOM for XHTML. For reuse of code, you can write your own classes extending DOM classes to get configurable components.
If you don't want to use DOM or want to use plain text for generating the XML, just approach it like any other template, e.g.
<root>
<albums>
<album id="<?php echo $albumId; ?>">
<title><?php echo $title; ?></title>
... other elements ...
</album>
</albums>
</root>
You can store your XMl string in a .php file then render it to get final formatted XMl string. In many cases simpler than playing with XMl writers
File template.php
<root>
<albums>
<album id="<?php echo $data['albumId']; ?>">
<title><?php echo $data['title']; ?></title>
... other elements ...
</album>
</albums>
</root>
Render
function render($template, array $data)
{
ob_start();
include $template;
return ob_get_clean();
}
I think it's echo($_xml);
Related
I have an xml file slider.xml with html code inside:
<?xml version="1.0" encoding="UTF-8"?>
<content>
<title>Slider</title>
<head>
<script async="async" src='ws-custom/plugins/slider.js'></script>
<script async="defer" src='ws-custom/plugins/functions.js'></script>
</head>
<footer>
<script async="defer" src='ws-custom/plugins/jquery.js'></script>
</footer>
</content>
In PHP I would like to:
1. load it (using simplexml, dom or other better solution) and store in a variable $xml;
2. create an array $head with both $xml->head->children();
3. return the original html code for $head[0] and $head[1].
I have tried using this code:
$xml = simplexml_load_file('slider.xml');
$head = $xml->head->children();
foreach($head as $element){
echo $element->asXML();
}
but it returns self-closing tags:
<script async="async" src="ws-custom/plugins/slider.js"/>
<script async="defer" src="ws-custom/plugins/functions.js"/>
which is not valid html code for W3C http://validator.w3.org/nu/
I would like also to be able to write only async, i.e.
because it's valid html, but with simplexml it's not valid xml.
Thank you very much.
Best regards.
I've edited the script, now it works perfectly.
Note please the row 6:
$element[] = null;
<?php
$xml = new DOMDocument();
$xml = simplexml_load_file('slider.xml');
$head = $xml->head->children();
foreach($head as $element){
$element[] = null;
echo $element->asXML().PHP_EOL;
}
SimpleXML can't output the empty tags properly, you should use DOMDocument instead (LIBXML_NOEMPTYTAG doesn't work in SimpleXML)...
$xml = new DOMDocument('1.0');
$xml->load("slider.xml");
$head = $xml->getElementsByTagName("head");
$headScripts= $head[0]->getElementsByTagName("script");
foreach($headScripts as $element){
echo $xml->saveXML($element, LIBXML_NOEMPTYTAG).PHP_EOL;
}
This code gets a start point (the <head> tag), as you only want the first one it uses [0] and finds the <script> tags inside the start point.
Which with the test source gives...
<script async="async" src="ws-custom/plugins/slider.js"></script>
<script async="defer" src="ws-custom/plugins/functions.js"></script>
I'm trying to parse an xml file and print the items in different order and also with some other text between. The xml file is something like this
<list>
<item>
<price>200</price>
<title>Title1</title>
<description>something here</description>
</item>
<item>
<price>350</price>
<title>Title2</title>
<description>something there</description>
</item>
</list>
and I want to have the output exactly like this, 2 different lines:
"Title1","something here","","200","1",""
"Title2","something there","","350","1",""
It's important to see quotes and commas.
I'm using this, but it is not enough. I don't know what to do next...
<?php
//Initialize the XML parser
$parser=xml_parser_create();
//Function to use at the start of an element
function start($parser,$element_name,$element_attrs)
{
switch($element_name)
{
case "PRICE":
echo """;
break;
case "TITLE":
echo """;
break;
case "DESCRIPTION":
echo """;
}
}
//Function to use at the end of an element
function stop($parser,$element_name)
{
echo "",";
}
//Function to use when finding character data
function char($parser,$data)
{
echo $data;
}
//Specify element handler
xml_set_element_handler($parser,"start","stop");
//Specify data handler
xml_set_character_data_handler($parser,"char");
//Open XML file
$fp=fopen("shopmania_ro.xml","r");
//Read data
while ($data=fread($fp,4096))
{
xml_parse($parser,$data,feof($fp)) or
die (sprintf("XML Error: %s at line %d",
xml_error_string(xml_get_error_code($parser)),
xml_get_current_line_number($parser)));
}
//Free the XML parser
xml_parser_free($parser);
?>
Thank you in advance.
I have another code
<?php
$xfile = "file.xml";
$xparser=xml_parser_create();
xml_set_character_data_handler($xparser, "cdataHandler");
if(!($fp=fopen($xfile,"r")))
{
die ("File does not exist");
}
while($data=fread($fp, 4096))
{
if(!xml_parse($xparser,$data,feof($fp)))
{
die("XML parse error: xml_error_string(xml_get_error_code($xparser))");
}
}
xml_parser_free($xml_parser);
function cdataHandler($xparser, $cdata)
{
echo "$cdata";
}
?>
and the output is
200 Title1 something here 350 Title2 something there
I don't know how to extract data and print it in the way that I want. Any help?
Sorry, I'm a newbie...
That's exactely what the XSLT stylesheet language was made for. Transforming XML documents to different formats. PHP comes with the XSL extension that's pretty easy to use. Examples are there, too.
EDIT
If that's an overkill for your purpose you should take a look at PHP's SimpleXML extension that allows you to use a node like you would use an object.
EDIT 2
$xmlstr = <<<XML
<?xml version='1.0' standalone='yes'?>
<list>
<item>
<price>200</price>
<title>Title1</title>
<description>something here</description>
</item>
...
</list>
XML;
$xml = simplexml_load_string($xmlstr);
$list = $xml->list;
foreach ( $list->item as $item ) {
// Not sure if this works, but if it doesn't, substitute the sprintf
// with plain string concatenation
echo sprintf(
'"%s","%s","","%d","1",""',
$item->title,
$item->description,
$item->price
);
}
I know i have bothered all of you with my questions but i have a question about php and xml
i am trying to store all the values of the pages in xml so i would create a multilingual website
after searching i have got to a way but and i tried to alter it a little bit
there is my xml files:
en.xml:
<?xml version="1.0" encoding="UTF-8"?>
<main>
<!--Page Titles-->
<freeEaHdr>
<![CDATA[Get in the game!]]>
</freeEaHdr>
<freeEaSubhdr>
<![CDATA[Load up your Xperia™ PLAY with 4 exciting EA titles for<span style="color:#ff9c00;"> FREE</span>]]>
</freeEaSubhdr>
<!--Page Titles-->
</main>
and there is my ar.xml
<?xml version="1.0" encoding="UTF-8"?>
<main>
<!--Page Titles-->
<freeEaHdr>
<![CDATA[ادخل اللعبة]]>
</freeEaHdr>
<freeEaSubhdr>
<![CDATA[حمل الاكسبيريا الان]]>
</freeEaSubhdr>
<!--Page Titles-->
</main>
and i have created an select_lang.php
<?php
function select_lang(){
if(isset($_GET['lang'])){
$lang = $_GET['lang'];
if($lang == "en"){
$xml = simplexml_load_file("en.xml");
} else{
$xml = simplexml_load_file("ar.xml");
}
} else {
$xml = simplexml_load_file("en.xml");
}
return $xml;
}
?>
and the final page was index.php
<?php
include("select_lang.php");
select_lang();
?>
<div><?php echo $xml->freeEaHdr; ?></div>
<div><?php echo $xml-> freeEaSubhdr; ?></div>
english
arabic
now of course i get errors in index.php as for the main xml variable is not defined so if anybody has a solution
Thanks in advance
and sorry for bothering you
Your select_lang() function returns the created SimpleXML object $xml. You then try to use this object in your index.php file, but you haven't actually assigned the return value of select_lang() to anything.
Simply doing
$xml = select_lang();
instead of
select_lang();
will let you actually use the returned XML object in your index.php file.
try to:
<?php
include("select_lang.php");
$xml = select_lang(); //change this line
?>
I have a PHP include that inserts an html form into another html form. When the form gets included I now have two form headers. Is there a php tag I could use that would allow me to...
<form id="orderform">
<!-- <?php for the include FROM here?> -->
PROD:<input class="ProductName" type="text" size="75">|
Discount:<input class="Discount" type="text" size="3">|
QTY:<input class="qty" type="text" size="6">|
Line/Total:<input class="LineTotal" type="text" size="9" disabled>
<!-- <?php for the include TO here?> -->
</form>
So the include would go into that file with the form in it and get the specified HTML?
Is this possible?
EDIT
<?php
$dom = new DOMDocument();
$html = 'phptest3.php';
$dom->loadHTMLFile($html);
$div = $dom->getElementById("divtagid");
echo $div->nodeValue;
?>
This only returns the text. How do I get the HTML form elements in the divtagid?
You should best look into php functions for this.
<?php
function form_tag_wrapper($form) {
return '<form id="orderform">'. $form .'</form>';
}
function form_contents() {
return 'PROD:<input class="ProductName" type="text" size="75">
...
Line/Total:<input class="LineTotal" type="text" size="9" disabled>';
}
?>
You will use this as:
$form = form_contents();
print form_tag_wrapper($form);
Or, as a oneliner:
print form_tag_wrapper(form_contents());
No, there isn't an alternate way to include a portion of a file. Consider: how would you describe to such a function where to start and end inclusion? How would the function know what you want?
As suggested, the best approach would be to refactor the included file. If that isn't an option (I can't imagine why it wouldn't be), another route is to use variables or constants in the included file to denote which portions should be output. Something like this:
#File: form_template.php
<?php if (!isset($include_form_header) || $include_form_header == true) { ?>
<form id="orderform">
<?php } ?>
PROD:<input class="ProductName" type="text" size="75">|
Discount:<input class="Discount" type="text" size="3">|
QTY:<input class="qty" type="text" size="6">|
Line/Total:<input class="LineTotal" type="text" size="9" disabled>
<?php if (!isset($include_form_header) || $include_form_header == true) { ?>
</form>
<?php } ?>
Now, when you want to stop the form header from being output:
$include_form_header = false;
include('form_template.php');
This is nasty, IMO. When someone else (or the future you) edits form_template.php, it may not be apparent when or why $include_form_header would be set. This kind of reliance on variables declared in external files can lead to spaghetti code.
You're far better building separate templates for different purposes (or directly echoing trivial output, like one line of html to open or close a form), for instance:
<?php
#File: order_form_wrapper.php
echo '<form id="orderform">';
?>
<?php
#File: product_fields.php
echo 'PROD:<input class="ProductName" type="text" size="75">';
echo 'Discount:<input class="Discount" type="text" size="3">';
echo 'QTY:<input class="qty" type="text" size="6">|';
echo 'Line/Total:<input class="LineTotal" type="text" size="9" disabled>';
?>
// form with wrapper
include 'order_form_wrapper.php';
include 'product_fields.php';
echo '</form>';
// different form with wrapper
include 'some_other_form_wrapper.php';
include 'product_fields.php';
include 'some_other_fields.php';
echo '</form>';
Last option, if you have absolutely no access to the template, can't modify it, can only include it, then you could use output buffering to include the file, load the resulting HTML into DOMDocument, then peal off the wrapping form tags. Take a look at the code... this isn't exactly "neat" either:
function extract_form_contents($template)
// enable output buffer, include file, get buffer contents & turn off buffer
ob_start();
include $template;
$form = ob_get_clean();
ob_end_clean();
// create a new DOMDocument & load the form HTML
$doc = new DOMDocument();
$doc->loadHTML($form);
// since we are working with an HTML fragment here, remove <!DOCTYPE, likewise remove <html><body></body></html>
$doc->removeChild($doc->firstChild);
$doc->replaceChild($doc->firstChild->firstChild->firstChild, $doc->firstChild);
// make a container for the extracted elements
$div = $doc->createElement('div');
// grab the form
$form = $doc->getElementsByTagName('form');
if ($form->length < 1)
return '';
$form = $form->item(0);
// loop the elements, clone, place in div
$nb = $form->childNodes->length;
if ($nb == 0)
return '';
for($pos=0; $pos<$nb; $pos++) {
$node = $form->childNodes->item($pos);
$div->appendChild($node->cloneNode(true));
}
// swap form for div
$doc->replaceChild($div, $form);
return $doc->saveHTML();
}
$contents = extract_form_contents('my_form_template.php');
You can structure your include file like an XML file with processing instructionsXML (DOMProcessingInstructionDocs). Such a file would only miss the XML root element, which could be added on the fly.
The benefit of this is, that it is compatible with both XHTML and PHP as long as you write PHP with the standard tags like <?php ... ?> because those are a valid XML processing instruction. Let's start with a simple, XHTML only example, the principle with PHP code is actually the same, but why make it complicated?
include.php:
<form id="orderform">
Text: <input name="element" />
</form>
To create an include function that can deal with this, it only needs to parse the XML file and return the fragment in question, e.g. everything inside the <form> tag. XML parsing ships with PHP, so everything is already ready to action.
function incXML($file, $id = NULL)
{
if (!($xml = file_get_contents($file)))
throw new Exception('File IO error.');
$xml = '<template>' . $xml . '</template>';
$doc = new DOMDocument();
if (!$doc->loadXML($xml))
throw new InvalidArgumentException('Invalid file.');
// #todo add HTML namespace if you want to support it
// fetch the contents of the file however you need to,
// e.g. with an xpath query, I leave this for a training
// and just do a plastic getElementById here which does NOT
// work w/o proper DTD support, it's just for illustration.
if (NULL === $id)
{
$part = $doc;
}
else
{
if (!$part = $doc->getElementById($id))
throw new InvalidArgumentException('Invalid ID.');
}
$buffer = '';
foreach($part->childNodes as $node)
{
$buffer .= $doc->saveXML($node);
}
return 'data:text/html;base64,' . base64_encode($buffer);
}
Usage:
<?php
include(incXML('include.php', 'orderform'))
?>
You don't need to change any of your template files as long as they contain XHTML/PHP in the end with such a method.
I'm generating a ton of XML that is to be passed to an API as a post variable when a user click on a form button. I also want to be able to show the user the XML before hand.
The code is sorta like the following in structure:
<?php
$lots of = "php";
?>
<xml>
<morexml>
<?php
while(){
?>
<somegeneratedxml>
<?php } ?>
<lastofthexml>
<?php ?>
<html>
<pre>
The XML for the user to preview
</pre>
<form>
<input id="xml" value="theXMLagain" />
</form>
</html>
My XML is being generated with a few while loops and stuff. It then needs to be shown in the two places (the preview and the form value).
My question is. How do I capture the generated XML in a variable or whatever so I only have to generate it once and then just print it out as apposed to generating it inside the preview and then again inside the form value?
<?php ob_start(); ?>
<xml/>
<?php $xml = ob_get_clean(); ?>
<input value="<?php echo $xml ?>" />͏͏͏͏͏͏
Put this at your start:
ob_start();
And to get the buffer back:
$value = ob_get_contents();
ob_end_clean();
See http://us2.php.net/manual/en/ref.outcontrol.php and the individual functions for more information.
It sounds like you want PHP Output Buffering
ob_start();
// make your XML file
$out1 = ob_get_contents();
//$out1 now contains your XML
Note that output buffering stops the output from being sent, until you "flush" it. See the Documentation for more info.
When using frequently, a little helper could be helpful:
class Helper
{
/**
* Capture output of a function with arguments and return it as a string.
*/
public static function captureOutput(callable $callback, ...$args): string
{
ob_start();
$callback(...$args);
$output = ob_get_contents();
ob_end_clean();
return $output;
}
}
You could try this:
<?php
$string = <<<XMLDoc
<?xml version='1.0'?>
<doc>
<title>XML Document</title>
<lotsofxml/>
<fruits>
XMLDoc;
$fruits = array('apple', 'banana', 'orange');
foreach($fruits as $fruit) {
$string .= "\n <fruit>".$fruit."</fruit>";
}
$string .= "\n </fruits>
</doc>";
?>
<html>
<!-- Show XML as HTML with entities; saves having to view source -->
<pre><?=str_replace("<", "<", str_replace(">", ">", $string))?></pre>
<textarea rows="8" cols="50"><?=$string?></textarea>
</html>