XmlClient
Miko's XmlClient provides easy XML fetching and parsing from web services. Supports both file_get_contents and cURL methods with SSL verification and timeout options.
XmlClient Methods Summary
| Method |
Description |
create($options) | Create new XmlClient instance |
get($url) | Fetch XML using file_get_contents |
getWithCurl($url) | Fetch XML using cURL |
XmlResponse Methods Summary
| Method |
Description |
isSuccess() | Check if request was successful |
xml() | Get SimpleXMLElement object |
error() | Get error message if failed |
toArray() | Convert XML to array |
find($xpath) | Find elements by XPath query |
first($xpath) | Get first matching element |
attribute($name) | Get attribute value from root |
value($path) | Get text value by XPath |
Basic Usage
use Miko\Core\Http\XmlClient;
// Create client
$client = XmlClient::create();
// Fetch XML
$response = $client->get('https://example.com/feed.xml');
if ($response->isSuccess()) {
$xml = $response->xml();
echo $xml->title;
}
Configuration Options
// Create with custom options
$client = XmlClient::create([
'timeout' => 30, // Request timeout in seconds
'user_agent' => 'Miko/1.0', // User agent string
'verify_ssl' => true // SSL certificate verification
]);
// Disable SSL for development
$client = XmlClient::create([
'verify_ssl' => false
]);
Fetching Methods
Using file_get_contents
$client = XmlClient::create();
// Simple GET request
$response = $client->get('https://example.com/data.xml');
if ($response->isSuccess()) {
$data = $response->toArray();
print_r($data);
}
Using cURL
$client = XmlClient::create([
'timeout' => 60
]);
// cURL with follow redirects
$response = $client->getWithCurl('https://example.com/feed.xml');
if ($response->isSuccess()) {
$xml = $response->xml();
}
Response Handling
Check Success
$response = $client->get('https://example.com/data.xml');
if ($response->isSuccess()) {
// Process XML
$xml = $response->xml();
} else {
// Handle error
echo "Error: " . $response->error();
}
Get Raw XML
$response = $client->get('https://example.com/data.xml');
// Get SimpleXMLElement
$xml = $response->xml();
// Access elements
echo $xml->title;
echo $xml->description;
// Loop through items
foreach ($xml->item as $item) {
echo $item->name;
}
Convert to Array
$response = $client->get('https://example.com/data.xml');
// Convert entire XML to array
$array = $response->toArray();
// Access as array
echo $array['title'];
echo $array['items'][0]['name'];
XPath Queries
Find Elements
$response = $client->get('https://example.com/catalog.xml');
// Find all products
$products = $response->find('//product');
foreach ($products as $product) {
echo $product->name . ': ' . $product->price . "\n";
}
// Find products with specific attribute
$activeProducts = $response->find('//product[@status="active"]');
Get First Match
$response = $client->get('https://example.com/catalog.xml');
// Get first product
$firstProduct = $response->first('//product');
if ($firstProduct) {
echo $firstProduct->name;
}
// Get specific element
$title = $response->first('//channel/title');
Get Value
$response = $client->get('https://example.com/rss.xml');
// Get text value directly
$title = $response->value('//channel/title');
$description = $response->value('//channel/description');
// Get root element value
$rootValue = $response->value();
Get Attribute
$response = $client->get('https://example.com/data.xml');
// Get attribute from root element
$version = $response->attribute('version');
$encoding = $response->attribute('encoding');
Practical Examples
RSS Feed Reader
class RssFeedReader
{
private XmlClient $client;
public function __construct()
{
$this->client = XmlClient::create([
'timeout' => 30,
'user_agent' => 'MyApp RSS Reader/1.0'
]);
}
public function getFeed(string $url): array
{
$response = $this->client->get($url);
if (!$response->isSuccess()) {
throw new Exception("Failed to fetch feed: " . $response->error());
}
$items = [];
foreach ($response->find('//item') as $item) {
$items[] = [
'title' => (string)$item->title,
'link' => (string)$item->link,
'description' => (string)$item->description,
'pubDate' => (string)$item->pubDate
];
}
return [
'title' => $response->value('//channel/title'),
'description' => $response->value('//channel/description'),
'items' => $items
];
}
}
// Usage
$reader = new RssFeedReader();
$feed = $reader->getFeed('https://example.com/rss.xml');
echo "Feed: " . $feed['title'] . "\n";
foreach ($feed['items'] as $item) {
echo "- " . $item['title'] . "\n";
}
Currency Exchange Rate
class CurrencyService
{
private XmlClient $client;
public function __construct()
{
$this->client = XmlClient::create(['timeout' => 15]);
}
public function getRates(string $base = 'USD'): array
{
$url = "https://api.example.com/rates.xml?base={$base}";
$response = $this->client->getWithCurl($url);
if (!$response->isSuccess()) {
return [];
}
$rates = [];
foreach ($response->find('//rate') as $rate) {
$currency = (string)$rate['currency'];
$value = (float)$rate;
$rates[$currency] = $value;
}
return $rates;
}
public function convert(float $amount, string $from, string $to): float
{
$rates = $this->getRates($from);
if (!isset($rates[$to])) {
throw new Exception("Currency {$to} not found");
}
return $amount * $rates[$to];
}
}
// Usage
$currency = new CurrencyService();
$rates = $currency->getRates('EUR');
$usdAmount = $currency->convert(100, 'EUR', 'USD');
Product Catalog Import
use Miko\Core\Http\XmlClient;
use Miko\Log\Logger;
class CatalogImporter
{
private XmlClient $client;
public function __construct()
{
$this->client = XmlClient::create([
'timeout' => 120,
'verify_ssl' => true
]);
}
public function import(string $url): array
{
$response = $this->client->getWithCurl($url);
if (!$response->isSuccess()) {
Logger::error("Catalog import failed", ['error' => $response->error()]);
return [];
}
$products = [];
foreach ($response->find('//product') as $product) {
$products[] = [
'sku' => (string)$product->sku,
'name' => (string)$product->name,
'price' => (float)$product->price,
'stock' => (int)$product->stock,
'category' => (string)$product->category,
'active' => (string)$product['status'] === 'active'
];
}
Logger::general('Imported products', ['count' => count($products)], 'INFO');
return $products;
}
}
// Usage
$importer = new CatalogImporter();
$products = $importer->import('https://supplier.com/catalog.xml');
foreach ($products as $product) {
// Save to database
Product::updateOrCreate(
['sku' => $product['sku']],
$product
);
}
Sitemap Parser
class SitemapParser
{
private XmlClient $client;
public function __construct()
{
$this->client = XmlClient::create();
}
public function getUrls(string $sitemapUrl): array
{
$response = $this->client->get($sitemapUrl);
if (!$response->isSuccess()) {
return [];
}
$urls = [];
// Handle sitemap index
$sitemaps = $response->find('//sitemap/loc');
if (!empty($sitemaps)) {
foreach ($sitemaps as $loc) {
$urls = array_merge($urls, $this->getUrls((string)$loc));
}
return $urls;
}
// Handle regular sitemap
foreach ($response->find('//url') as $url) {
$urls[] = [
'loc' => (string)$url->loc,
'lastmod' => (string)$url->lastmod ?: null,
'priority' => (float)($url->priority ?: 0.5)
];
}
return $urls;
}
}
// Usage
$parser = new SitemapParser();
$urls = $parser->getUrls('https://example.com/sitemap.xml');
foreach ($urls as $url) {
echo $url['loc'] . " (Priority: " . $url['priority'] . ")\n";
}
Error Handling
$client = XmlClient::create();
$response = $client->get('https://example.com/data.xml');
if (!$response->isSuccess()) {
$error = $response->error();
// Log the error
Logger::error("XML fetch failed", [
'url' => 'https://example.com/data.xml',
'error' => $error
]);
// Handle specific errors
if (str_contains($error, 'Failed to fetch')) {
// Network error
} elseif (str_contains($error, 'Failed to parse')) {
// Invalid XML
}
}
Comparison: get() vs getWithCurl()
| Feature |
get() |
getWithCurl() |
| Method | file_get_contents | cURL |
| Follow Redirects | No | Yes |
| Performance | Faster for simple requests | Better for complex requests |
| Error Details | Basic | Detailed |
| Recommended | Simple XML feeds | APIs, authenticated requests |
// Use get() for simple feeds
$response = $client->get('https://example.com/simple.xml');
// Use getWithCurl() for APIs with redirects
$response = $client->getWithCurl('https://api.example.com/data.xml');