How to Run the PHP Inside an XML File

I’ve recently been diving into an interesting project where I had to work with PHP code embedded inside an XML file a setup that at first glance seemed unusual to me. I’m going to walk you through the entire process: explaining the XML structure, how PHP code is embedded within it, and how to execute that PHP code using a custom runner script. I hope that by the end of this article, you’ll have a clear understanding of both the challenges and practical solutions for working with such hybrid files.

Explanation of the XML Code

When I first encountered the XML file, I noticed that it defined a “product” with a variety of metadata elements. Let me break it down for you:

Structure and Purpose

  • Basic Information:
    Elements like <title>, <description>, and <version> provide general details about the product. They serve as the core metadata that describes what the product is and its version.
  • URLs:
    The <url> and <versioncheckurl> elements are used for linking to external resources. The former might be for product details or documentation, while the latter could be for checking if a product update is available.
  • Dependencies:
    The <dependencies> section lists requirements, such as a minimum and maximum version of another component (for example, “vbulletin”). This ensures that the product only works when specific conditions are met.
  • Plugins:
    The <plugins> element contains one or more <plugin> entries. Each plugin has its own metadata (like <title> and <hookname>) and, importantly, a <phpcode> element where PHP code is stored.

Embedding PHP in XML

Why Embed PHP?

The <phpcode> element in the XML file uses a CDATA section:

<![CDATA[
echo "and now we're doing php for some reason???" . $qux;
]]>
  • What is CDATA?
    CDATA tells the XML parser to treat the enclosed text as character data instead of XML markup. This is essential because PHP code can include characters (like < and >) that would normally be interpreted as XML tags.
  • Why Use CDATA?
    Without CDATA, these special characters could break the XML format. By wrapping the PHP code in a CDATA section, I can safely include code without worrying about XML parsing errors.

Running PHP from an XML File

The Challenge

Since the file isn’t a standard PHP file—it lacks the usual <?php ... ?> tags—the PHP interpreter wouldn’t automatically recognize or execute the embedded code.

The Solution

I needed to create a separate PHP “runner” script that would:

  • Load the XML file (using a parser like SimpleXML).
  • Extract the PHP code from the CDATA sections within <phpcode>.
  • Execute that code (typically using eval() or by writing it to a temporary file and including it).

Sample PHP Runner Script with Practical Enhancements

Here’s a complete PHP script that I developed. It not only loads and executes the embedded PHP code but also introduces a simple plugin system where context variables can be passed to the plugin code.

<?php
// Define a context array that holds variables accessible by plugins
$context = [
'qux' => 'This is a sample variable from the runner script',
// You can add more context variables here
];

// Load the XML file
$xml = simplexml_load_file('product.xml');
if (!$xml) {
die('Error loading XML file');
}

// Check if plugins exist
if (!isset($xml->plugins->plugin)) {
die('No plugins found in the XML file.');
}

// Loop over each plugin and execute its PHP code
foreach ($xml->plugins->plugin as $plugin) {
echo "Executing plugin: " . $plugin->title . "\n";

// Extract PHP code from the <phpcode> element
$code = (string) $plugin->phpcode;

// Optionally, you can wrap the code in a function to pass in context
$pluginFunction = function($context) use ($code) {
// Extract context variables to the local scope
extract($context);
// Evaluate the PHP code
eval($code);
};

// Execute the plugin code, passing in the context
$pluginFunction($context);

echo "\n"; // For readability between plugin outputs
}
?>

How This Runner Script Works

Context Passing

I created a $context array containing variables (like $qux) that might be useful to multiple plugins. Inside the anonymous function, extract($context); makes these variables available in the local scope, so the embedded PHP code can reference them directly.

Loading and Parsing XML

The script leverages simplexml_load_file() to read the XML file (named product.xml in this case). It then verifies whether the <plugins> element exists and iterates through each <plugin> entry.

Executing Embedded PHP Code

For each plugin, I extract the PHP code from its <phpcode> element as a string. I then execute that code inside an anonymous function using eval().

Note: Using eval() can be risky if the XML content isn’t trusted. In production, you should ensure the XML is secure or consider an alternative approach.

Output

The script prints out each plugin’s title before executing its PHP code. For instance, you might see an output similar to this:

Executing plugin: some plugin
and now we're doing php for some reason??? This is a sample variable from the runner script

Additional Practical Enhancements

Throughout the project, I found several ways to improve the solution:

  • Error Handling:
    It’s a good idea to add try/catch blocks or error checking around eval() to gracefully handle any syntax errors in the plugin code.
  • Plugin Metadata:
    The runner could use additional metadata (such as hookname or executionorder) to determine the order of execution or conditionally run plugins based on the environment.
  • Security Considerations:
    If the XML file originates from an untrusted source, sanitizing the input or using a safer execution model is essential. One strategy is to limit which functions the plugin code can call or to run the code in a sandboxed environment.
  • Logging:
    Implementing logging to record when plugins are executed, any errors that occur, and the context in which they were run can be very helpful for debugging and auditing.
  • Extensibility:
    Designing the system so that each plugin can return a value or modify the context further enhances its flexibility. After all plugins execute, the script could then use the updated context data to drive further actions.

Final Thoughts

I must say, working with PHP code embedded in an XML file was an eye-opening experience for me. Although it initially seemed confusing, breaking down the process and building a practical runner script helped me understand the benefits and challenges of such an approach. Not only did I learn about XML structure and CDATA sections, but I also got hands-on experience with dynamic code execution and building a simple plugin system.

This project reinforced the importance of understanding the tools and data formats you’re working with. Whether it’s ensuring secure execution with eval() or designing systems to be extensible and maintainable, every challenge is an opportunity to grow as a developer. I hope you found this exploration as intriguing and enlightening as I did!

Related blog posts