-
-
Save goedecke/03e9c7c178ff947b1e9d9eaea4bbe369 to your computer and use it in GitHub Desktop.
<?php | |
$xml = simplexml_load_file('test.xml'); | |
$ns = $xml->getNamespaces(true); | |
$xml->registerXPathNamespace('c', $ns['cfdi']); | |
$xml->registerXPathNamespace('t', $ns['tfd']); | |
//EMPIEZO A LEER LA INFORMACION DEL CFDI E IMPRIMIRLA | |
foreach ($xml->xpath('//cfdi:Comprobante') as $cfdiComprobante){ | |
echo $cfdiComprobante['version']; | |
echo "<br />"; | |
echo $cfdiComprobante['fecha']; | |
echo "<br />"; | |
echo $cfdiComprobante['sello']; | |
echo "<br />"; | |
echo $cfdiComprobante['total']; | |
echo "<br />"; | |
echo $cfdiComprobante['subTotal']; | |
echo "<br />"; | |
echo $cfdiComprobante['certificado']; | |
echo "<br />"; | |
echo $cfdiComprobante['formaDePago']; | |
echo "<br />"; | |
echo $cfdiComprobante['noCertificado']; | |
echo "<br />"; | |
echo $cfdiComprobante['tipoDeComprobante']; | |
echo "<br />"; | |
} | |
foreach ($xml->xpath('//cfdi:Comprobante//cfdi:Emisor') as $Emisor){ | |
echo $Emisor['rfc']; | |
echo "<br />"; | |
echo $Emisor['nombre']; | |
echo "<br />"; | |
} | |
foreach ($xml->xpath('//cfdi:Comprobante//cfdi:Emisor//cfdi:DomicilioFiscal') as $DomicilioFiscal){ | |
echo $DomicilioFiscal['pais']; | |
echo "<br />"; | |
echo $DomicilioFiscal['calle']; | |
echo "<br />"; | |
echo $DomicilioFiscal['estado']; | |
echo "<br />"; | |
echo $DomicilioFiscal['colonia']; | |
echo "<br />"; | |
echo $DomicilioFiscal['municipio']; | |
echo "<br />"; | |
echo $DomicilioFiscal['noExterior']; | |
echo "<br />"; | |
echo $DomicilioFiscal['codigoPostal']; | |
echo "<br />"; | |
} | |
foreach ($xml->xpath('//cfdi:Comprobante//cfdi:Emisor//cfdi:ExpedidoEn') as $ExpedidoEn){ | |
echo $ExpedidoEn['pais']; | |
echo "<br />"; | |
echo $ExpedidoEn['calle']; | |
echo "<br />"; | |
echo $ExpedidoEn['estado']; | |
echo "<br />"; | |
echo $ExpedidoEn['colonia']; | |
echo "<br />"; | |
echo $ExpedidoEn['noExterior']; | |
echo "<br />"; | |
echo $ExpedidoEn['codigoPostal']; | |
echo "<br />"; | |
} | |
foreach ($xml->xpath('//cfdi:Comprobante//cfdi:Receptor') as $Receptor){ | |
echo $Receptor['rfc']; | |
echo "<br />"; | |
echo $Receptor['nombre']; | |
echo "<br />"; | |
} | |
foreach ($xml->xpath('//cfdi:Comprobante//cfdi:Receptor//cfdi:Domicilio') as $ReceptorDomicilio){ | |
echo $ReceptorDomicilio['pais']; | |
echo "<br />"; | |
echo $ReceptorDomicilio['calle']; | |
echo "<br />"; | |
echo $ReceptorDomicilio['estado']; | |
echo "<br />"; | |
echo $ReceptorDomicilio['colonia']; | |
echo "<br />"; | |
echo $ReceptorDomicilio['municipio']; | |
echo "<br />"; | |
echo $ReceptorDomicilio['noExterior']; | |
echo "<br />"; | |
echo $ReceptorDomicilio['noInterior']; | |
echo "<br />"; | |
echo $ReceptorDomicilio['codigoPostal']; | |
echo "<br />"; | |
} | |
foreach ($xml->xpath('//cfdi:Comprobante//cfdi:Conceptos//cfdi:Concepto') as $Concepto){ | |
echo "<br />"; | |
echo $Concepto['unidad']; | |
echo "<br />"; | |
echo $Concepto['importe']; | |
echo "<br />"; | |
echo $Concepto['cantidad']; | |
echo "<br />"; | |
echo $Concepto['descripcion']; | |
echo "<br />"; | |
echo $Concepto['valorUnitario']; | |
echo "<br />"; | |
echo "<br />"; | |
} | |
foreach ($xml->xpath('//cfdi:Comprobante//cfdi:Impuestos//cfdi:Traslados//cfdi:Traslado') as $Traslado){ | |
echo $Traslado['tasa']; | |
echo "<br />"; | |
echo $Traslado['importe']; | |
echo "<br />"; | |
echo $Traslado['impuesto']; | |
echo "<br />"; | |
echo "<br />"; | |
} | |
//ESTA ULTIMA PARTE ES LA QUE GENERABA EL ERROR | |
foreach ($xml->xpath('//t:TimbreFiscalDigital') as $tfd) { | |
echo $tfd['selloCFD']; | |
echo "<br />"; | |
echo $tfd['FechaTimbrado']; | |
echo "<br />"; | |
echo $tfd['UUID']; | |
echo "<br />"; | |
echo $tfd['noCertificadoSAT']; | |
echo "<br />"; | |
echo $tfd['version']; | |
echo "<br />"; | |
echo $tfd['selloSAT']; | |
} | |
?> |
Hola... muchas gracias por el codigo, funciona a la perfeccion.... Alguien sabe como interactuar con las mayusculas y minusculas de los nombres de los atributos?... necesito leer CDFI en versiones diferentes y a veces necesito las minusculas ['selloSAT'] y a veces mayusculas ['SelloSAT']? no puedo modificar el codigo cada vez, si no que necesito que sea interactivo y el codigo pueda detectar y leerlo.
Gracias y saludos!
$version = (string)$cfdiComprobante[0]['Version'];
//Encontrar version del xml
if ($version == NULL){
$version = (string)$cfdiComprobante[0]['version'];
}
Ya con esto sabes con que version estas trabajando.
con un if ($version == "3.2"){
//codigo que hacer si es 3.2
}elseif ($version == "3.3{
//codigo que hacer si es 3.3
}
Eso es en cuanto a diferentes versiones pero dentro del texto puedes homogeneizar todo a minusculas o Mayusculas para un tratamiento en el cual sin importar las version te maneje el mismo resultado. strupper strlower
Genial!, pero hay alguna solución en la que se pueda iterar el xml como un array anidado, me imagino que debe ser como un foreach()... pero no estoy completamente seguro....
$ruta = //ruta hacia la carpeta donde están tus xml's
$dir = opendir($ruta);
while ($file = readdir($dir)) {
if ($file != "." && $file != ".." && substr($file,-4)==".xml"){
$xml = simplexml_load_file($ruta . $file);
$ns = $xml->getNamespaces(true);
$xml->registerXPathNamespace('c', $ns['cfdi']);
$xml->registerXPathNamespace('t', $ns['tfd']);
..... Aquí va el resto del código
}
}
Genial!, pero hay alguna solución en la que se pueda iterar el xml como un array anidado, me imagino que debe ser como un foreach()... pero no estoy completamente seguro....
$ruta = //ruta hacia la carpeta donde están tus xml's
$dir = opendir($ruta);while ($file = readdir($dir)) {
if ($file != "." && $file != ".." && substr($file,-4)==".xml"){
$xml = simplexml_load_file($ruta . $file);
$ns = $xml->getNamespaces(true);
$xml->registerXPathNamespace('c', $ns['cfdi']);
$xml->registerXPathNamespace('t', $ns['tfd']);
..... Aquí va el resto del código
}
}
en ves de while ($file = readdir($dir)) usa scandir()
Con esto te saltas los dos puntos
$files = array_slice(scandir('/path/to/directory/'), 2);
y así reduces el uso de memoria y de recursos en paths con cientos de archivos.
y yo manejaría una función por separado
Esto te regresa un arreglo con todos los archivos, en la carpeta o subcarpetas de forma recursiva esto por si tienes alguna distribución por año mes del guardado de tus archivos.
function scanDirectories($rootDir, $allData=array()) {
$invisibleFileNames = array(".", "..", ".htaccess", ".htpasswd");
$dirContent = scandir($rootDir);
foreach($dirContent as $key => $content) {
$path = $rootDir.'/'.$content;
if(!in_array($content, $invisibleFileNames)) {
if(is_file($path) && is_readable($path)) {
$allData[] = $path;
}elseif(is_dir($path) && is_readable($path)) {
$allData = scanDirectories($path, $allData);
}
}
}
return $allData;
}
Eso es en cuanto a diferentes versiones pero dentro del texto puedes homogeneizar todo a minusculas o Mayusculas para un tratamiento en el cual sin importar las version te maneje el mismo resultado. strupper strlower
Genial!, pero hay alguna solución en la que se pueda iterar el xml como un array anidado, me imagino que debe ser como un foreach()... pero no estoy completamente seguro....
$ruta = //ruta hacia la carpeta donde están tus xml's
$dir = opendir($ruta);
while ($file = readdir($dir)) {
if ($file != "." && $file != ".." && substr($file,-4)==".xml"){
$xml = simplexml_load_file($ruta . $file);
$ns = $xml->getNamespaces(true);
$xml->registerXPathNamespace('c', $ns['cfdi']);
$xml->registerXPathNamespace('t', $ns['tfd']);
..... Aquí va el resto del código
}
}en ves de while ($file = readdir($dir)) usa scandir()
Con esto te saltas los dos puntos
$files = array_slice(scandir('/path/to/directory/'), 2);
y así reduces el uso de memoria y de recursos en paths con cientos de archivos.y yo manejaría una función por separado
Esto te regresa un arreglo con todos los archivos, en la carpeta o subcarpetas de forma recursiva esto por si tienes alguna distribución por año mes del guardado de tus archivos.
function scanDirectories($rootDir, $allData=array()) {
$invisibleFileNames = array(".", "..", ".htaccess", ".htpasswd");
$dirContent = scandir($rootDir);
foreach($dirContent as $key => $content) {
$path = $rootDir.'/'.$content;
if(!in_array($content, $invisibleFileNames)) {
if(is_file($path) && is_readable($path)) {
$allData[] = $path;
}elseif(is_dir($path) && is_readable($path)) {
$allData = scanDirectories($path, $allData);
}
}
}
return $allData;
}
Excelente! Muchas gracias.
Hi!
Por si les es de utilidad, se pueden obtener los namespaces y analizar todo el documento:
$xmlString = 'AQUI EL CFDI'
$xmlObject = simplexml_load_string($xmlString);
$ns = $xmlObject->getNamespaces(true);
Y con una función recursiva, estructurarlo como un arreglo y evitarse el tema de buscar con XPath:
function XMLNode($XMLNode, $ns)
{
//
$nodes = array();
$response = array();
$attributes = array();
// first item ?
$_isfirst = true;
// each namespace
// - xmlns:cfdi="http://www.sat.gob.mx/cfd/3"
// - xmlns:tfd="http://www.sat.gob.mx/TimbreFiscalDigital"
foreach ($ns as $eachSpace) {
//
// each node
foreach ($XMLNode->children($eachSpace) as $_tag => $_node) {
//
$_value = $this->XMLNode($_node, $ns);
// exists $tag in $children?
if (key_exists($_tag, $nodes)) {
if ($_isfirst) {
$tmp = $nodes[$_tag];
unset($nodes[$_tag]);
$nodes[] = $tmp;
$is_first = false;
}
$nodes[] = $_value;
} else {
$nodes[$_tag] = $_value;
}
}
}
//
$attributes = array_merge(
$attributes,
current($XMLNode->attributes())
);
// nodes ?
if (count($nodes)) {
$response = array_merge(
$response,
$nodes
);
}
// attributes ?
if (count($attributes)) {
$response = array_merge(
$response,
$attributes
);
}
return (empty($response) ? null : $response);
}
//
$response = XMLNode($xmlObject, $ns);
Si revisan la respuesta, podrán obtener algo como:
[Concepto] => Array
(
[Impuestos] => Array
(
[Traslados] => Array
(
[Traslado] => Array
(
[Base] => 7867.14
[Impuesto] => 002
[TipoFactor] => Tasa
[TasaOCuota] => 0.160000
[Importe] => 1258.74
)
)
[Retenciones] => Array
(
[0] => Array
(
[Base] => 7867.140000
[Impuesto] => 001
[TipoFactor] => Tasa
[TasaOCuota] => 0.100000
[Importe] => 786.71
)
[1] => Array
(
[Base] => 7867.140000
[Impuesto] => 002
[TipoFactor] => Tasa
[TasaOCuota] => 0.106667
[Importe] => 839.16
)
)
)
[ClaveProdServ] => XXXXXXXX
[Cantidad] => 1
[ClaveUnidad] => E48
[Unidad] => Unidad de servicio
[Descripcion] => HONORARIOS
[ValorUnitario] => 7867.14
[Importe] => 7867.14
)
Finalmente, hace mucho más sentido usar el documento, como un arreglo:
<cfdi:Complemento>
<tfd:TimbreFiscalDigital Version="1.1" UUID="0DE6AEB1-E8FG-41CD-881D-A6AB18F0415D" ... />
</cfdi:Complemento>
echo($response['Complementos']['TimbreFiscalDigital']['UUID']);
My2C
Hola... muchas gracias por el codigo, funciona a la perfeccion.... Alguien sabe como interactuar con las mayusculas y minusculas de los nombres de los atributos?... necesito leer CDFI en versiones diferentes y a veces necesito las minusculas ['selloSAT'] y a veces mayusculas ['SelloSAT']? no puedo modificar el codigo cada vez, si no que necesito que sea interactivo y el codigo pueda detectar y leerlo.
Gracias y saludos!
Igual y si conviertes las variables a minúsculas ayuda (strtolower)
Hi!
Por si les es de utilidad, se pueden obtener los namespaces y analizar todo el documento:
$xmlString = 'AQUI EL CFDI' $xmlObject = simplexml_load_string($xmlString); $ns = $xmlObject->getNamespaces(true);
Y con una función recursiva, estructurarlo como un arreglo y evitarse el tema de buscar con XPath:
function XMLNode($XMLNode, $ns) { // $nodes = array(); $response = array(); $attributes = array(); // first item ? $_isfirst = true; // each namespace // - xmlns:cfdi="http://www.sat.gob.mx/cfd/3" // - xmlns:tfd="http://www.sat.gob.mx/TimbreFiscalDigital" foreach ($ns as $eachSpace) { // // each node foreach ($XMLNode->children($eachSpace) as $_tag => $_node) { // $_value = $this->XMLNode($_node, $ns); // exists $tag in $children? if (key_exists($_tag, $nodes)) { if ($_isfirst) { $tmp = $nodes[$_tag]; unset($nodes[$_tag]); $nodes[] = $tmp; $is_first = false; } $nodes[] = $_value; } else { $nodes[$_tag] = $_value; } } } // $attributes = array_merge( $attributes, current($XMLNode->attributes()) ); // nodes ? if (count($nodes)) { $response = array_merge( $response, $nodes ); } // attributes ? if (count($attributes)) { $response = array_merge( $response, $attributes ); } return (empty($response) ? null : $response); } // $response = XMLNode($xmlObject, $ns);
Si revisan la respuesta, podrán obtener algo como:
[Concepto] => Array ( [Impuestos] => Array ( [Traslados] => Array ( [Traslado] => Array ( [Base] => 7867.14 [Impuesto] => 002 [TipoFactor] => Tasa [TasaOCuota] => 0.160000 [Importe] => 1258.74 ) ) [Retenciones] => Array ( [0] => Array ( [Base] => 7867.140000 [Impuesto] => 001 [TipoFactor] => Tasa [TasaOCuota] => 0.100000 [Importe] => 786.71 ) [1] => Array ( [Base] => 7867.140000 [Impuesto] => 002 [TipoFactor] => Tasa [TasaOCuota] => 0.106667 [Importe] => 839.16 ) ) ) [ClaveProdServ] => XXXXXXXX [Cantidad] => 1 [ClaveUnidad] => E48 [Unidad] => Unidad de servicio [Descripcion] => HONORARIOS [ValorUnitario] => 7867.14 [Importe] => 7867.14 )
Finalmente, hace mucho más sentido usar el documento, como un arreglo:
<cfdi:Complemento> <tfd:TimbreFiscalDigital Version="1.1" UUID="0DE6AEB1-E8FG-41CD-881D-A6AB18F0415D" ... /> </cfdi:Complemento> echo($response['Complementos']['TimbreFiscalDigital']['UUID']);
My2C
Pues si, pero eso te consume mas recursos de memoria y aquí abría que evaluar el tamaño de documentos a leer o bien el numero de items a extraer, y si de convertir a arreglo simple para extraer datos, pues recomiendo que todo lo vuelvas Arreglo y eso es fácil con esto que publique hace como 4 años
https://gist.github.com/goedecke/20dc74132bd928f37d339178863bfbc3
Entiendo.
Prefiero claridad en la implementación (que sea sencillo para el equipo de trabajo), y lo del consumo de memoria pues es relativo, como bien mencionas; depende del tamaño de documentos a leer (¿facturas de 50Mb?) y lo del # de items a extraer, pues.
En fin, fue solo un aporte que muestra que cada quien tiene una visión distinta para lograr sus objetivos.
Saludos.
Hi!
Por si les es de utilidad, se pueden obtener los namespaces y analizar todo el documento:
$xmlString = 'AQUI EL CFDI' $xmlObject = simplexml_load_string($xmlString); $ns = $xmlObject->getNamespaces(true);
Y con una función recursiva, estructurarlo como un arreglo y evitarse el tema de buscar con XPath:
function XMLNode($XMLNode, $ns) { // $nodes = array(); $response = array(); $attributes = array(); // first item ? $_isfirst = true; // each namespace // - xmlns:cfdi="http://www.sat.gob.mx/cfd/3" // - xmlns:tfd="http://www.sat.gob.mx/TimbreFiscalDigital" foreach ($ns as $eachSpace) { // // each node foreach ($XMLNode->children($eachSpace) as $_tag => $_node) { // $_value = $this->XMLNode($_node, $ns); // exists $tag in $children? if (key_exists($_tag, $nodes)) { if ($_isfirst) { $tmp = $nodes[$_tag]; unset($nodes[$_tag]); $nodes[] = $tmp; $is_first = false; } $nodes[] = $_value; } else { $nodes[$_tag] = $_value; } } } // $attributes = array_merge( $attributes, current($XMLNode->attributes()) ); // nodes ? if (count($nodes)) { $response = array_merge( $response, $nodes ); } // attributes ? if (count($attributes)) { $response = array_merge( $response, $attributes ); } return (empty($response) ? null : $response); } // $response = XMLNode($xmlObject, $ns);
Si revisan la respuesta, podrán obtener algo como:
[Concepto] => Array ( [Impuestos] => Array ( [Traslados] => Array ( [Traslado] => Array ( [Base] => 7867.14 [Impuesto] => 002 [TipoFactor] => Tasa [TasaOCuota] => 0.160000 [Importe] => 1258.74 ) ) [Retenciones] => Array ( [0] => Array ( [Base] => 7867.140000 [Impuesto] => 001 [TipoFactor] => Tasa [TasaOCuota] => 0.100000 [Importe] => 786.71 ) [1] => Array ( [Base] => 7867.140000 [Impuesto] => 002 [TipoFactor] => Tasa [TasaOCuota] => 0.106667 [Importe] => 839.16 ) ) ) [ClaveProdServ] => XXXXXXXX [Cantidad] => 1 [ClaveUnidad] => E48 [Unidad] => Unidad de servicio [Descripcion] => HONORARIOS [ValorUnitario] => 7867.14 [Importe] => 7867.14 )
Finalmente, hace mucho más sentido usar el documento, como un arreglo:
<cfdi:Complemento> <tfd:TimbreFiscalDigital Version="1.1" UUID="0DE6AEB1-E8FG-41CD-881D-A6AB18F0415D" ... /> </cfdi:Complemento> echo($response['Complementos']['TimbreFiscalDigital']['UUID']);
My2C
Excelente código, funciona de maravilla... Gracias por la aportación.. sólo una observación, en la línea del merge() me mandaba un Warning: Warning: array_key_exists() expects parameter 2 to be array, boolean given in
Se corrigió con un cast a array
Código anterior:
$attributes = array_merge(
$attributes,
current($XMLNode->attributes())
);
Código nuevo:
$attributes = array_merge(
$attributes,
(array)current($XMLNode->attributes())
);
Gracias nuevamente por la aportación..
Saludos.
Me faltó felicitarte goedecke... excelente código.. muy sencillo de implementar y entender...!!! Gracias nuevamente..
Se corrigió con un cast a array
Código anterior:
$attributes = array_merge(
$attributes,
current($XMLNode->attributes())
);
Código nuevo:
$attributes = array_merge(
$attributes,
(array)current($XMLNode->attributes())
);Gracias nuevamente por la aportación..
Vale, haré el cambio.. la realidad es que no lo pasé por stan para hacer un análisis del código (amén de las pruebas unitarias/funcionales), gracias por la retro.
para los que necesiten leer dentro de Complementos en facturas P
// verifica que sea P y obtiene el monto if($tipocomprobante == 'P') { foreach ($xml->xpath('//cfdi:Comprobante//cfdi:Complemento//pago10:Pagos//pago10:Pago') as $Pago10){ $montop = $Pago10['Monto']; //drupal_set_message('monto: '.$montop, 'status', FALSE); $node->field_factura_pago10_monto['und'][0]['value'] = $montop; } }
EDIT: este codigo esta mas limpio
` // verifica que sea P y obtiene el monto if($tipocomprobante == 'P') { $xml->registerXPathNamespace('p', $ns['pago10']); // set monto pago 10 foreach ($xml->xpath('//p:Pago') as $pago10) { $montop = $pago10['Monto']; $node->field_factura_pago10_monto['und'][0]['value'] = $montop; } // set id ducumentp rel $documentosRel = $xml->xpath('//p:DoctoRelacionado'); foreach ($documentosRel as $key) { $node->field_pago_10_doctorel_id_dcto['und'][0]['value'] = $key['IdDocumento']; } } // fin comprobante P`
para los que necesiten leer dentro de Complementos en facturas P
// verifica que sea P y obtiene el monto if($tipocomprobante == 'P') { foreach ($xml->xpath('//cfdi:Comprobante//cfdi:Complemento//pago10:Pagos//pago10:Pago') as $Pago10){ $montop = $Pago10['Monto']; //drupal_set_message('monto: '.$montop, 'status', FALSE); $node->field_factura_pago10_monto['und'][0]['value'] = $montop; } }
EDIT: este codigo esta mas limpio
` // verifica que sea P y obtiene el monto if($tipocomprobante == 'P') { $xml->registerXPathNamespace('p', $ns['pago10']); // set monto pago 10 foreach ($xml->xpath('//p:Pago') as $pago10) { $montop = $pago10['Monto']; $node->field_factura_pago10_monto['und'][0]['value'] = $montop; } // set id ducumentp rel $documentosRel = $xml->xpath('//p:DoctoRelacionado'); foreach ($documentosRel as $key) { $node->field_pago_10_doctorel_id_dcto['und'][0]['value'] = $key['IdDocumento']; } } // fin comprobante P`
Hola. Estoy recibiendo varios complementos que tienen dos o más pagos y cada pago a su vez tiene sus Documentos relacionados. ¿Cómo puedo leer el complemento de manera que pueda ver qué Documentos relacionados están amparados con cada Pago o monto? Por ejemplo:
cfdi:Complemento
<pago10:Pagos Version="1.0">
<pago10:Pago FechaPago="2019-06-21T12:07:57" FormaDePagoP="03" MonedaP="MXN" Monto="150000.00 ">
<pago10:DoctoRelacionado IdDocumento="UUID1" Serie="PC" Folio="230156" MonedaDR="MXN" MetodoDePagoDR="PPD" NumParcialidad="1 " ImpSaldoAnt="75000.00 " ImpPagado="75000.00 " ImpSaldoInsoluto="0.00 "/>
<pago10:DoctoRelacionado IdDocumento="UUID2" Serie="PC" Folio="230160" MonedaDR="MXN" MetodoDePagoDR="PPD" NumParcialidad="1 " ImpSaldoAnt="75000.00 " ImpPagado="750000.00 " ImpSaldoInsoluto="0.00 "/>
</pago10:Pago>
<pago10:Pago FechaPago="2019-06-21T14:35:25" FormaDePagoP="03" MonedaP="MXN" Monto="100000.00 ">
<pago10:DoctoRelacionado IdDocumento="UUID3" Serie="PC" Folio="230181" MonedaDR="MXN" MetodoDePagoDR="PPD" NumParcialidad="1 " ImpSaldoAnt="20000.00 " ImpPagado="20000.00 " ImpSaldoInsoluto="0.00 "/>
<pago10:DoctoRelacionado IdDocumento="UUID4" Serie="PC" Folio="230236" MonedaDR="MXN" MetodoDePagoDR="PPD" NumParcialidad="1 " ImpSaldoAnt="30000.00 " ImpPagado="30000.00 " ImpSaldoInsoluto="0.00 "/>
<pago10:DoctoRelacionado IdDocumento="UUID5" Serie="PC" Folio="230238" MonedaDR="MXN" MetodoDePagoDR="PPD" NumParcialidad="1 " ImpSaldoAnt="50000.00 " ImpPagado="50000.00 " ImpSaldoInsoluto="0.00 "/>
</pago10:Pago>
</pago10:Pagos>
De esto quisiera obtener algo como
Pago 1 - Monto 150000 - UUID1 - UUID2
Pago 2 - Monto 100000 - UUID3 - UUID4 - UUID5
¿Es posible hacerlo con ese orden?
Porque lo que consigo es
Pago 1 - Monto
Pago 2- Monto
UUID1
UUID2
UUID3
UUID4
UUID5
Buenas tardes, estaba accediendo a las facturas pero hoy me genero este error y no encuentro el porque surge, si alguien pudiera dar un poco de ayuda lo agradeceria.
This page contains the following errors:
error on line 28 at column 182: xmlns:schemaLocation: 'http://www.sat.gob.mx/registrofiscal http://www.sat.gob.mx/sitio_internet/cfd/cfdiregistrofiscal/cfdiregistrofiscal.xsd' is not a valid URI
Below is a rendering of the page up to the first error.
Buenas tardes, estaba accediendo a las facturas pero hoy me genero este error y no encuentro el porque surge, si alguien pudiera dar un poco de ayuda lo agradeceria.
This page contains the following errors:
error on line 28 at column 182: xmlns:schemaLocation: 'http://www.sat.gob.mx/registrofiscal http://www.sat.gob.mx/sitio_internet/cfd/cfdiregistrofiscal/cfdiregistrofiscal.xsd' is not a valid URI
Below is a rendering of the page up to the first error.
¿tienes más información al respecto?
¿dónde se presenta el error, factura de ejemplo...?
para los que necesiten leer dentro de Complementos en facturas P
// verifica que sea P y obtiene el monto if($tipocomprobante == 'P') { foreach ($xml->xpath('//cfdi:Comprobante//cfdi:Complemento//pago10:Pagos//pago10:Pago') as $Pago10){ $montop = $Pago10['Monto']; //drupal_set_message('monto: '.$montop, 'status', FALSE); $node->field_factura_pago10_monto['und'][0]['value'] = $montop; } }
EDIT: este codigo esta mas limpio
` // verifica que sea P y obtiene el monto if($tipocomprobante == 'P') { $xml->registerXPathNamespace('p', $ns['pago10']); // set monto pago 10 foreach ($xml->xpath('//p:Pago') as $pago10) { $montop = $pago10['Monto']; $node->field_factura_pago10_monto['und'][0]['value'] = $montop; } // set id ducumentp rel $documentosRel = $xml->xpath('//p:DoctoRelacionado'); foreach ($documentosRel as $key) { $node->field_pago_10_doctorel_id_dcto['und'][0]['value'] = $key['IdDocumento']; } } // fin comprobante P`
para los que necesiten leer dentro de Complementos en facturas P
// verifica que sea P y obtiene el monto if($tipocomprobante == 'P') { foreach ($xml->xpath('//cfdi:Comprobante//cfdi:Complemento//pago10:Pagos//pago10:Pago') as $Pago10){ $montop = $Pago10['Monto']; //drupal_set_message('monto: '.$montop, 'status', FALSE); $node->field_factura_pago10_monto['und'][0]['value'] = $montop; } }
EDIT: este codigo esta mas limpio
` // verifica que sea P y obtiene el monto if($tipocomprobante == 'P') { $xml->registerXPathNamespace('p', $ns['pago10']); // set monto pago 10 foreach ($xml->xpath('//p:Pago') as $pago10) { $montop = $pago10['Monto']; $node->field_factura_pago10_monto['und'][0]['value'] = $montop; } // set id ducumentp rel $documentosRel = $xml->xpath('//p:DoctoRelacionado'); foreach ($documentosRel as $key) { $node->field_pago_10_doctorel_id_dcto['und'][0]['value'] = $key['IdDocumento']; } } // fin comprobante P`
Hola. Estoy recibiendo varios complementos que tienen dos o más pagos y cada pago a su vez tiene sus Documentos relacionados. ¿Cómo puedo leer el complemento de manera que pueda ver qué Documentos relacionados están amparados con cada Pago o monto? Por ejemplo:
cfdi:Complemento <pago10:Pagos Version="1.0"> <pago10:Pago FechaPago="2019-06-21T12:07:57" FormaDePagoP="03" MonedaP="MXN" Monto="150000.00 "> <pago10:DoctoRelacionado IdDocumento="UUID1" Serie="PC" Folio="230156" MonedaDR="MXN" MetodoDePagoDR="PPD" NumParcialidad="1 " ImpSaldoAnt="75000.00 " ImpPagado="75000.00 " ImpSaldoInsoluto="0.00 "/> <pago10:DoctoRelacionado IdDocumento="UUID2" Serie="PC" Folio="230160" MonedaDR="MXN" MetodoDePagoDR="PPD" NumParcialidad="1 " ImpSaldoAnt="75000.00 " ImpPagado="750000.00 " ImpSaldoInsoluto="0.00 "/> </pago10:Pago> <pago10:Pago FechaPago="2019-06-21T14:35:25" FormaDePagoP="03" MonedaP="MXN" Monto="100000.00 "> <pago10:DoctoRelacionado IdDocumento="UUID3" Serie="PC" Folio="230181" MonedaDR="MXN" MetodoDePagoDR="PPD" NumParcialidad="1 " ImpSaldoAnt="20000.00 " ImpPagado="20000.00 " ImpSaldoInsoluto="0.00 "/> <pago10:DoctoRelacionado IdDocumento="UUID4" Serie="PC" Folio="230236" MonedaDR="MXN" MetodoDePagoDR="PPD" NumParcialidad="1 " ImpSaldoAnt="30000.00 " ImpPagado="30000.00 " ImpSaldoInsoluto="0.00 "/> <pago10:DoctoRelacionado IdDocumento="UUID5" Serie="PC" Folio="230238" MonedaDR="MXN" MetodoDePagoDR="PPD" NumParcialidad="1 " ImpSaldoAnt="50000.00 " ImpPagado="50000.00 " ImpSaldoInsoluto="0.00 "/> </pago10:Pago> </pago10:Pagos>
De esto quisiera obtener algo como
Pago 1 - Monto 150000 - UUID1 - UUID2
Pago 2 - Monto 100000 - UUID3 - UUID4 - UUID5¿Es posible hacerlo con ese orden?
Porque lo que consigo es
Pago 1 - Monto
Pago 2- MontoUUID1
UUID2
UUID3
UUID4
UUID5
Quizás algo así?
foreach ($xml->xpath('//p:Pago') as $pago10) {
$montop = $pago10['Monto'];
$node->field_factura_pago10_monto['und'][0]['value'] = $montop;
// set id ducumentp rel
$documentosRel = $xml->xpath('//p:DoctoRelacionado');
foreach ($documentosRel as $key) {
$node->field_pago_10_doctorel_id_dcto['und'][0]['value'] = $key['IdDocumento'];
}
}
Buenas tardes, estaba accediendo a las facturas pero hoy me genero este error y no encuentro el porque surge, si alguien pudiera dar un poco de ayuda lo agradeceria.
This page contains the following errors:
error on line 28 at column 182: xmlns:schemaLocation: 'http://www.sat.gob.mx/registrofiscal http://www.sat.gob.mx/sitio_internet/cfd/cfdiregistrofiscal/cfdiregistrofiscal.xsd' is not a valid URI
Below is a rendering of the page up to the first error.
Hola viejo tu error es muy simple, tienes dos url en el codigo
'http://www.sat.gob.mx/registrofiscal
y
http://www.sat.gob.mx/sitio_internet/cfd/cfdiregistrofiscal/cfdiregistrofiscal.xsd
Elimina http://www.sat.gob.mx/registrofiscal y con eso debe de funcionar
Buenas tardes, estaba accediendo a las facturas pero hoy me genero este error y no encuentro el porque surge, si alguien pudiera dar un poco de ayuda lo agradeceria.
This page contains the following errors:
error on line 28 at column 182: xmlns:schemaLocation: 'http://www.sat.gob.mx/registrofiscal http://www.sat.gob.mx/sitio_internet/cfd/cfdiregistrofiscal/cfdiregistrofiscal.xsd' is not a valid URI
Below is a rendering of the page up to the first error.Hola viejo tu error es muy simple, tienes dos url en el codigo
'http://www.sat.gob.mx/registrofiscal
y
http://www.sat.gob.mx/sitio_internet/cfd/cfdiregistrofiscal/cfdiregistrofiscal.xsdElimina http://www.sat.gob.mx/registrofiscal y con eso debe de funcionar
Hola hermano, acabo de realizar tu procedimiento y efectivamente eliminando esa linea se puede visualizar la factura, muchas gracias, sabes si hay alguna manera de leer la factura y poder eliminar esa url de manera programada? de ante mano muchas gracias
Buenas, tengo un problemita a la hora de tratar de agregar otro xpath un ejemplo seria este $xml->registerXPathNamespace('n', $ns['nomina12']);
No me detecta lo que vendria siendo la key de nomina12 apesar de que este aparezca en los xml, estoy empezando en esto y se me hace algo confuso, un saludo y muchas gracias
Es posible leer varios archivos desde un input ? eso ya lo hice solamente con un archivo , necesito extraer información de cada uno de ellos para poder hacer un varios análisis de los ingresos y egresos supongo que es con un foreach o sera mejor subir los archivos a una carpeta y leerlos todos ?
Me fue útil para solucionar un problema en especifico con un nodo en la versión 4.0, muchas gracias.
Me fue útil para solucionar un problema en especifico con un nodo en la versión 4.0, muchas gracias.
ejemplo..., cómo fue tu escenario?
foreach ($xml->xpath('//cfdi:Comprobante//cfdi:Impuestos//cfdi:Traslados//cfdi:Traslado') as $traslados) {
$t.= (string)$traslados['TipoFactor'] .'-' .(string)$traslados['TasaOCuota'].(string)$traslados['Importe'].'
';
}
Estoy tratando de leer los traslados dentro de impuestos pero tambien me trae los traslados de los conceptos a pesar de que especifico el xpath...
Buenas! alguna actualizacion para que acepte la version 4 o mayor?
Esto me funciono para extraer el UUID del xml con la version 4.0
$uuid = (string) $xml->xpath('//tfd:TimbreFiscalDigital/@uuid')[0];
Entiendo. Prefiero claridad en la implementación (que sea sencillo para el equipo de trabajo), y lo del consumo de memoria pues es relativo, como bien mencionas; depende del tamaño de documentos a leer (¿facturas de 50Mb?) y lo del # de items a extraer, pues.
En fin, fue solo un aporte que muestra que cada quien tiene una visión distinta para lograr sus objetivos. Saludos.
Estoy de acuerdo con esto, implementé tu solución para un detalle específico que tenía accediendo a atributos anidados, te agradezco el aporte.
los echo en blanco son
echo "<br/>"