atk14/xmole

Simple XML parser with path-based access to elements, attributes and subtrees

Maintainers

Package info

github.com/atk14/XMole

pkg:composer/atk14/xmole

Statistics

Installs: 22 732

Dependents: 4

Suggesters: 0

Stars: 0

Open Issues: 0

v1.0.4 2026-05-06 13:40 UTC

This package is auto-updated.

Last update: 2026-05-06 13:41:12 UTC


README

Tests

XMole is a simple PHP XML parser that turns XML into a traversable object tree. It wraps PHP's built-in expat parser and adds a convenient path-based API for reading element data, attributes, and subtrees.

Installation

composer require atk14/xmole

Basic usage

Pass XML directly to the constructor, or call parse() separately:

$xm = new XMole('
  <order id="42" status="pending">
    <customer>John Doe</customer>
    <item sku="ABC">Widget</item>
    <item sku="XYZ">Gadget</item>
  </order>
');

$xm->get_data("customer");            // "John Doe"
$xm->get_attribute("order", "id");    // "42"
$xm->get_root_name();                 // "order"

Path syntax

Paths work similarly to XPath but use a simpler /-separated format.

// Absolute path — must match from the root
$xm->get_data("/order/customer");

// Relative path — matches anywhere in the tree
$xm->get_data("customer");

// Root element shorthand
$xm->get_data("/");           // data of the root element
$xm->get_attributes();        // attributes of the root element
$xm->get_attribute("id");     // attribute of the root element (path can be omitted)

Trailing slashes are ignored: "order/" and "order" are equivalent.

Reading data and attributes

// Element text content
$xm->get_data("customer");                    // "John Doe"

// Single attribute
$xm->get_attribute("order", "status");        // "pending"
$xm->get_attribute("status");                 // same — root element attribute shorthand

// All attributes as an associative array
$xm->get_attributes("order");                 // ["id" => "42", "status" => "pending"]
$xm->get_root_attributes();                   // same for the root element

// Returns null when the element or attribute is not found
$xm->get_data("nonexistent");                 // null
$xm->get_attribute("order", "nonexistent");   // null

Whitespace at the beginning and end of element data is trimmed by default. To disable trimming:

$xm = new XMole($xml, ["trim_data" => false]);
// or
$xm->set_trim_data(false);

Navigating subtrees

Use get_xmole() to get a subtree as a new XMole instance:

$item = $xm->get_xmole("item");       // first matching <item>
$item->get_data();                    // "Widget"  (root element data)
$item->get_attribute("sku");          // "ABC"

Use get_xmoles() to get all matching elements:

$items = $xm->get_xmoles("item");     // array of XMole instances

$items[0]->get_data();                // "Widget"
$items[1]->get_data();                // "Gadget"

Iterating over children

// Access children by index
$first  = $xm->get_child(0);
$second = $xm->get_child(1);

// Get all direct children at once
$children = $xm->get_children();
foreach ($children as $child) {
    echo $child->get_root_name() . ": " . $child->get_data() . "\n";
}

// Iterate sequentially with get_next_child()
while ($child = $xm->get_next_child()) {
    echo $child->get_attribute("sku") . "\n";
}

// Reset the internal pointer to start over
$xm->reset_next_child_index();

Error handling

parse() returns false on failure. Error details are available via get_error_message() or the optional reference parameters:

$xm = new XMole();
if (!$xm->parse($xml, $err_code, $err_message)) {
    echo $err_message;  // e.g. "XML parser error (76): Mismatched tag on line 3"
}

error() returns true if the last parse failed:

$xm = new XMole($possibly_invalid_xml);
if ($xm->error()) {
    echo $xm->get_error_message();
}

Encoding conversion

XMole can transparently convert character encoding while parsing, using the atk14/translate library. Input encoding is auto-detected from the XML declaration if not set explicitly.

$xm = new XMole();
$xm->set_input_encoding("UTF-8");
$xm->set_output_encoding("WINDOWS-1250");
$xm->parse($xml);

Set both at once with set_encoding():

$xm->set_encoding("ISO-8859-2");

Comparing XML

is_same_like() and the static AreSame() compare two XML documents structurally. Attribute order is ignored.

$xml1 = '<item id="1" name="foo" />';
$xml2 = '<item name="foo" id="1" />';   // same attributes, different order

XMole::AreSame($xml1, $xml2);           // true

$xm = new XMole($xml1);
$xm->is_same_like($xml2);               // true
$xm->is_same_like('<item id="2" />');   // false

// Returns null if either document is invalid
XMole::AreSame($xml1, '<bad>');         // null

Building XML safely

Two static helpers encode values for safe embedding in XML:

// For text content
$xml = "<description>" . XMole::ToXML($user_input) . "</description>";

// For attribute values
$xml = '<item name="' . XMole::ToAttribsValue($name) . '" />';

ToXML() encodes & < > " ' and strips control characters invalid in XML 1.0. ToAttribsValue() encodes the same characters and also converts newlines to spaces.

Testing

composer install
cd test && ../vendor/bin/run_unit_tests

License

XMole is free software distributed under the terms of the MIT license.