Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/eclipxe13/CfdiUtils/llms.txt

Use this file to discover all available pages before exploring further.

CfdiUtils represents every CFDI document — and every complement or addenda attached to it — as an in-memory tree of Node objects. The tree is intentionally lightweight: each node stores only a name, a flat map of string attributes, and an ordered list of child nodes. This design mirrors the structure of CFDI XML, where all meaningful data lives in element attributes and element nesting, not in text content. The Node and Nodes classes live in the CfdiUtils\Nodes namespace and are the foundation that every other CfdiUtils component — validators, creators, and element builders — builds on top of.

The Node Class

CfdiUtils\Nodes\Node is the fundamental building block. Its constructor accepts three parameters and an optional fourth:
name
string
required
The XML element name. Whitespace is trimmed from both ends. The name must be a valid XML element name; an invalid name throws \UnexpectedValueException. Once set, the name is immutable.
attributes
string[]
default:"[]"
An associative array of name => value pairs imported as the node’s initial attributes.
children
NodeInterface[]
default:"[]"
An array of Node (or any NodeInterface) objects imported as the initial child collection.
value
string
default:"\"\""
Optional text content of the element, used by the few SAT complements that store values as text nodes rather than attributes.
<?php
use CfdiUtils\Nodes\Node;

$node = new Node('cfdi:Comprobante', [
    'Version'  => '4.0',
    'SubTotal' => '1000.00',
]);
The node name() method returns the element name as a string. You cannot rename a node after construction.

Attribute Access

Attributes are managed internally by a CfdiUtils\Nodes\Attributes collection and are exposed through PHP’s ArrayAccess interface directly on the Node object. The access rules are:
  • Read always returns a string. Reading an attribute that does not exist returns an empty string (''), never null.
  • Write accepts a string or any object implementing __toString().
  • isset() returns true only when the attribute has been explicitly set.
  • unset() removes the attribute entirely.
<?php
use CfdiUtils\Nodes\Node;

$node = new Node('root', ['id' => '1']);

echo $node['id'];                             // '1'
echo $node['missing'];                        // '' (empty string, no error)
echo isset($node['missing']) ? 'yes' : 'no'; // 'no'

$node['atributo'] = 'valor';  // set an attribute
unset($node['id']);            // remove an attribute

// Iterate all attributes via attributes()
foreach ($node->attributes() as $name => $value) {
    echo $name . ': ' . $value . PHP_EOL;
}
The attributes() method returns the underlying Attributes collection. You can also call addAttributes(array $attributes) to merge an associative array of values into the node at once.

Child Node Access

Child nodes are managed by a CfdiUtils\Nodes\Nodes collection. Iterating a Node directly (via foreach) iterates over its children — not its attributes.
<?php
use CfdiUtils\Nodes\Node;

$parent = new Node('cfdi:Conceptos');
$child  = new Node('cfdi:Concepto', ['Descripcion' => 'Servicio de consultoría']);

$parent->addChild($child);

// Iterate children directly on the node
foreach ($parent as $concepto) {
    echo $concepto['Descripcion'] . PHP_EOL;
}

// Or access the Nodes collection explicitly
$children = $parent->children(); // returns Nodes
echo $children->count();         // 1
Key child-related methods on Node:
MethodReturn typeDescription
addChild(NodeInterface $node)NodeInterfaceAppends $node to the children collection and returns it
children()NodesReturns the mutable Nodes collection
count()intNumber of direct children

Search Methods

Node provides three recursive search helpers that traverse the child tree by element name path:
searchNode(string ...$searchPath)
Node|null
Walks the given path of element names, returning the first matching node at the end of the path, or null if any step fails.
searchNodes(string ...$searchPath)
Nodes
Like searchNode, but returns all sibling nodes matching the last name in the path, wrapped in a new Nodes collection. Adding or removing from this collection does not affect the original tree; however, mutating the returned nodes’ attributes does.
searchAttribute(string ...$searchPath)
string
Like searchNode, but the last argument is treated as an attribute name. Returns the attribute value if found, or an empty string otherwise.
<?php
// Given: $cfdi is the root Node for a CFDI document
$tfd = $cfdi->searchNode('cfdi:Complemento', 'tfd:TimbreFiscalDigital');

if (null !== $tfd) {
    echo $tfd['UUID'];
}

// Get all Concepto nodes inside Conceptos
$conceptos = $cfdi->searchNodes('cfdi:Conceptos', 'cfdi:Concepto');
foreach ($conceptos as $concepto) {
    echo $concepto['Descripcion'] . PHP_EOL;
}

// Get an attribute directly without checking for null nodes
$uuid = $cfdi->searchAttribute('cfdi:Complemento', 'tfd:TimbreFiscalDigital', 'UUID');

The Nodes Collection

CfdiUtils\Nodes\Nodes is a typed, ordered collection of NodeInterface objects. It implements Countable and IteratorAggregate. Core methods:
MethodDescription
add(NodeInterface ...$nodes)Adds one or more nodes; duplicates (same instance) are silently ignored
remove(NodeInterface $node)Removes the given node instance
removeAll()Clears the collection
exists(NodeInterface $node)Returns true if the exact instance is already in the collection
indexOf(NodeInterface $node)Returns the zero-based position, or -1 if not found
get(int $position)Returns the node at the given zero-based position
first()Returns the first node or null
firstNodeWithName(string $nodeName)Returns the first node whose name() matches, or null
getNodesByName(string $nodeName)Returns a new Nodes containing all nodes with the given name
importFromArray(NodeInterface[] $nodes)Bulk-adds an array of NodeInterface objects
setOrder(string[] $names)Sets the preferred child element sort order
count()Number of nodes
<?php
use CfdiUtils\Nodes\Nodes;
use CfdiUtils\Nodes\Node;

$nodes = new Nodes([
    new Node('cfdi:Traslado', ['Impuesto' => 'IVA']),
    new Node('cfdi:Traslado', ['Impuesto' => 'IEPS']),
]);

echo $nodes->count(); // 2

$iva = $nodes->firstNodeWithName('cfdi:Traslado');
echo $iva['Impuesto']; // 'IVA'

XmlNodeUtils

CfdiUtils\Nodes\XmlNodeUtils is a static utility class for converting between XML strings/DOM objects and the Node tree.
nodeFromXmlString(string $content)
NodeInterface
Parses a valid XML string and returns the root Node. Useful for loading a CFDI from a file.
nodeToXmlString(NodeInterface $node, bool $withXmlHeader = false)
string
Serializes a Node tree back to an XML string. Pass true for $withXmlHeader to include the <?xml ...?> declaration.
nodeFromXmlElement(DOMElement $element)
NodeInterface
Converts a DOMElement to a Node.
nodeToXmlElement(NodeInterface $node)
DOMElement
Converts a Node to a DOMElement (inside an owning DOMDocument).
nodeFromSimpleXmlElement(SimpleXMLElement $element)
NodeInterface
Converts a SimpleXMLElement to a Node.
nodeToSimpleXmlElement(NodeInterface $node)
SimpleXMLElement
Converts a Node to a SimpleXMLElement.
<?php
use CfdiUtils\Nodes\XmlNodeUtils;

// Load from file
$xmlContent = file_get_contents('/facturas/FE-00012847.xml');
$cfdi = XmlNodeUtils::nodeFromXmlString($xmlContent);

echo $cfdi->name();       // 'cfdi:Comprobante'
echo $cfdi['Version'];    // '4.0'

// Serialize back to XML
$xmlOut = XmlNodeUtils::nodeToXmlString($cfdi, true);
file_put_contents('/output/modified.xml', $xmlOut);
Node objects are not a faithful re-implementation of the full DOM. They store attributes, child elements, and simple text content only. Importing XML that contains mixed content (interleaved text and elements), processing instructions, or comments may result in data loss.

Text Content (NodeHasValueInterface)

Most CFDI documents store all meaningful data in attributes. However, a small number of SAT complements — notably the Complemento de facturas del sector de ventas al detalle — store values as element text nodes. Node implements NodeHasValueInterface, which provides:
MethodDescription
value(): stringReads the text content of the element
setValue(string $value): voidSets the text content of the element
<?php
$node = new \CfdiUtils\Nodes\Node('detalle', [], [], 'texto de contenido');
echo $node->value(); // 'texto de contenido'

$node->setValue('nuevo contenido');
echo $node->value(); // 'nuevo contenido'

Build docs developers (and LLMs) love