在每个父节点上计算具有相同名称的XML子级

时间:2017-11-19 17:55:33

标签: c# xml visual-studio linq

我有以下XML文件:

<if:Cuerpo Renglon="1" Cantidad="13" Concepto="SOPORTE DE FARO" PUnitario="387.04" Importe="5031.52" U_x0020_de_x0020_M="PIEZA" Material="F01030106" cfdiClaveProdServ="31162504" cfdiClaveUnidad="H87" cfdiDescuento="2113.24">
  <if:Aduana CodigoMultiple="Aduana" PedimentoAduanero="14  51  3475  4000268" />
  <if:Aduana CodigoMultiple="Aduana" PedimentoAduanero="14  51  3475  4000268" />
  <if:Aduana CodigoMultiple="Aduana" PedimentoAduanero="14  51  3475  4000507" />
  <if:Aduana CodigoMultiple="Aduana" PedimentoAduanero="14  51  3475  4000874" />
  <if:Traslado CodigoMultiple="TrasladoConcepto" cfdiBase="2918.28" cfdiImpuesto="002" cfdiTipoFactor="Tasa" cfdiTasaOCuota="0.160000" cfdiImporte="466.92" />
</if:Cuerpo>
<if:Cuerpo Renglon="2" Cantidad="13" Concepto="SOPORTE DE FARO" PUnitario="387.04" Importe="5031.52" U_x0020_de_x0020_M="PIEZA" Material="F01030106" cfdiClaveProdServ="31162504" cfdiClaveUnidad="H87" cfdiDescuento="2113.24">
  <if:Aduana CodigoMultiple="Aduana" PedimentoAduanero="14  51  3475  4000268" />
  <if:Aduana CodigoMultiple="Aduana" PedimentoAduanero="14  51  3475  4000268" />
  <if:Traslado CodigoMultiple="TrasladoConcepto" cfdiBase="2918.28" cfdiImpuesto="002" cfdiTipoFactor="Tasa" cfdiTasaOCuota="0.160000" cfdiImporte="466.92" />
</if:Cuerpo>

我想计算每个if:Aduana父节点有多少if:Cuerpo个节点。

例如,第一个if:Cuerpo节点有4个if:Aduana个子节点 第二个if:Cuerpo节点有2个if:Aduana个子节点。

这是完整的命名空间

  <cfdi:Addenda xmlns:if="https://www.interfactura.com/Schemas/Documentos" >
    <if:FacturaInterfactura TipoDocumentoId="0" TipoDocumento="Factura" Id="303019096">
      <if:Emisor RI="0000915" />
      <if:Receptor RI="9900136962" Activo="False" />
      <if:Encabezado IdInterno="303019096" TemplateId="78000937" Folio="928" FolioSerie="928-" SerieFolio="-928" MonedaDoc="MXN" MonedaDesc="Pesos" Status="1" CFD="True" Estatus="Por Pagar" ProcesoId="0" CondicionPago="60 días a partir entrega factu" Descuento="2113.24" SubTotal="5031.52" Total="3385.20" Moneda="MXN" LugarExpedicion="09319" TipoCambio="1.00000" TipoDocumento="Factura" metodoDePago="PUE" formaDePago="03" FolioReferencia="0740642450" RegimenFiscalEmisor="623" cfdiUsoCFDI="P01" cfdiFormaPago="03" cfdiMetodoPago="PUE" cfdiTipoRelacion="" VersionCFDI="3.3" Fecha="2017-11-18T14:15:41" cadenaOriginal="||1.1|199BEA24-32BC-4E30-8041-5DC1EADC70D8|2017-11-18T14:14:42|INT020124V62||8wyc7rDr2Vv9toCY/4ByZxrZIBYUtSycm2k6xZB5Rmgg+e5Cra1xhCArZR2w9y4K845Mr1xzxfVda6xUGie0YjKZYrlXRrhigvQ4K3EGUsFOYenDaT0DnzSIUCu8OhwBCaPsspUJzCngev6YqSPjjoCZATsvl21hljxXPuRjGjyJa8wYGUCWZzlU5ZfR65qjai9nNC0XeDyxGfZAwewbZL17RMLnH73TpPJbe7muGd1ts19EGVWCa22avj1SGBIjxJ1Dz+TPhuXk5qNI/iO5XLQWqWMUXVgnZrOSh7Gm2iR+E8Q5QV6fIytQj4g/K1EPyDJ6aD12zh4set3w+/Dn2Q==|20001000000300022323||" cadenaOriginalTimbre="||1.1|199BEA24-32BC-4E30-8041-5DC1EADC70D8|2017-11-18T14:14:42|INT020124V62||8wyc7rDr2Vv9toCY/4ByZxrZIBYUtSycm2k6xZB5Rmgg+e5Cra1xhCArZR2w9y4K845Mr1xzxfVda6xUGie0YjKZYrlXRrhigvQ4K3EGUsFOYenDaT0DnzSIUCu8OhwBCaPsspUJzCngev6YqSPjjoCZATsvl21hljxXPuRjGjyJa8wYGUCWZzlU5ZfR65qjai9nNC0XeDyxGfZAwewbZL17RMLnH73TpPJbe7muGd1ts19EGVWCa22avj1SGBIjxJ1Dz+TPhuXk5qNI/iO5XLQWqWMUXVgnZrOSh7Gm2iR+E8Q5QV6fIytQj4g/K1EPyDJ6aD12zh4set3w+/Dn2Q==|20001000000300022323||" cadenaOriginalEmisor="||3.3|928|2017-11-18T14:15:41|03|00001000000405697777|60 días a partir entrega factu|5031.52|2113.24|MXN|1.00000|3385.20|I|PUE|09319|CMC0712144R4|COMERCIALIZADORA DE MOTOCICLETAS DE CALIDAD, S.A. DE C.V.|623|PERP660325R60|PEDRO PEREYRA RABAGO|P01|31162504|13|H87|PIEZA|SOPORTE DE FARO|387.04|5031.52|2113.24|2918.28|002|Tasa|0.160000|466.92|14 51 3475 4000268|14 51 3475 4000268|14 51 3475 4000507|14 51 3475 4000874|002|Tasa|0.160000|466.92|466.92||" importeConLetra="**********************TRES MIL TRESCIENTOS OCHENTA Y CINCO PESOS 20/100 M.N.**********************">
        <if:Cuerpo Renglon="1" Cantidad="13" Concepto="SOPORTE DE FARO" PUnitario="387.04" Importe="5031.52" U_x0020_de_x0020_M="PIEZA" Material="F01030106" cfdiClaveProdServ="31162504" cfdiClaveUnidad="H87" cfdiDescuento="2113.24">
          <if:Aduana CodigoMultiple="Aduana" PedimentoAduanero="14  51  3475  4000268" />
          <if:Aduana CodigoMultiple="Aduana" PedimentoAduanero="14  51  3475  4000268" />
          <if:Aduana CodigoMultiple="Aduana" PedimentoAduanero="14  51  3475  4000507" />
          <if:Aduana CodigoMultiple="Aduana" PedimentoAduanero="14  51  3475  4000874" />
          <if:Traslado CodigoMultiple="TrasladoConcepto" cfdiBase="2918.28" cfdiImpuesto="002" cfdiTipoFactor="Tasa" cfdiTasaOCuota="0.160000" cfdiImporte="466.92" />
        </if:Cuerpo>
        <if:Cuerpo Renglon="2" Cantidad="13" Concepto="SOPORTE DE FARO" PUnitario="387.04" Importe="5031.52" U_x0020_de_x0020_M="PIEZA" Material="F01030106" cfdiClaveProdServ="31162504" cfdiClaveUnidad="H87" cfdiDescuento="2113.24">
          <if:Aduana CodigoMultiple="Aduana" PedimentoAduanero="14  51  3475  4000268" />
          <if:Aduana CodigoMultiple="Aduana" PedimentoAduanero="14  51  3475  4000268" />
          <if:Aduana CodigoMultiple="Aduana" PedimentoAduanero="14  51  3475  4000507" />
          <if:Aduana CodigoMultiple="Aduana" PedimentoAduanero="14  51  3475  4000874" />
          <if:Traslado CodigoMultiple="TrasladoConcepto" cfdiBase="2918.28" cfdiImpuesto="002" cfdiTipoFactor="Tasa" cfdiTasaOCuota="0.160000" cfdiImporte="466.92" />
        </if:Cuerpo>
      </if:Encabezado>
    </if:FacturaInterfactura>

1 个答案:

答案 0 :(得分:0)

正如@derloopkat所指出的,首先需要将cfdi XML命名空间添加到XML文件,并结束cfdi:Addenda的标记。否则,XML文档无效且无法处理。例如:

<cfdi:Addenda xmlns:cfdi="https://cfdi.namespace" xmlns:if="https://www.interfactura.com/Schemas/Documentos">
...
</cfdi:Addenda>

然后,您可以使用XDocument类加载XML文件,并使用Linq to XML查询来计算if:Aduana个元素。

const string IF_NAMESPACE = "https://www.interfactura.com/Schemas/Documentos";
const string PATH_TO_XML_FILE = @"C:\path_to_xml_file.xml";

// Load XML document from file
var doc = XDocument.Load(PATH_TO_XML_FILE);

// select all if:Cuerpo elements
var cuerpoElements = doc.Descendants(XName.Get("Cuerpo", IF_NAMESPACE));

// for each if:Cuerpo element, count it's descendant if:Aduana elements
// aduanaElementsCount contains array [4, 4]
var aduanaElementsCount = cuerpoElements.Select(cuerpo => cuerpo.Descendants(XName.Get("Aduana", IF_NAMESPACE)).Count()).ToArray();

有时我更喜欢使用XPath查询而不是Linq to XML,因为它有时会导致更短的代码。在这种特殊情况下,它实际上有点复杂,但您仍然可以使用相同的结果:

const string IF_NAMESPACE = "https://www.interfactura.com/Schemas/Documentos";
const string PATH_TO_XML_FILE = @"C:\path_to_xml_file.xml";

XmlDocument doc = new XmlDocument();
// Load XML document from file
doc.Load(PATH_TO_XML_FILE);

// Create namespace manager for XML namespaces used in XPath query
var ns = new XmlNamespaceManager(doc.NameTable);
ns.AddNamespace("if", IF_NAMESPACE);

var aduanaElementsCount = doc
    .SelectNodes("//if:Cuerpo", ns)// returns all if:Cuerpo nodes in XML document
    .Cast<IEnumerable>()// enables enumeration of selected nodes
    .Select(cuerpo => (cuerpo as XmlNode).SelectNodes(".//if:Aduana", ns).Count)// for each if:Cuerpo element, count it's descendant if:Aduana elements
    .ToArray();//returns array [4, 4]