Search code examples
c#xmlxsdlinq-to-xml

Get Particular value from xml inner elements with C#


I have a XML file with data as shown here:

<Invoice xmlns='urn:oasis:names:specification:ubl:schema:xsd:Invoice-2' xmlns:cac='urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2' xmlns:cbc='urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2' xmlns:ext='urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2'><ext:UBLExtensions>
    <ext:UBLExtension>
        <ext:ExtensionURI>urn:oasis:names:specification:ubl:dsig:enveloped:xades</ext:ExtensionURI>
        <ext:ExtensionContent>
            <sig:UBLDocumentSignatures xmlns:sig='urn:oasis:names:specification:ubl:schema:xsd:CommonSignatureComponents-2' xmlns:sac='urn:oasis:names:specification:ubl:schema:xsd:SignatureAggregateComponents-2' xmlns:sbc='urn:oasis:names:specification:ubl:schema:xsd:SignatureBasicComponents-2'>
                <sac:SignatureInformation>
                    <cbc:ID>urn:oasis:names:specification:ubl:signature:1</cbc:ID>
                    <sbc:ReferencedSignatureID>urn:oasis:names:specification:ubl:signature:Invoice</sbc:ReferencedSignatureID>
                    <ds:Signature xmlns:ds='http://www.w3.org/2000/09/xmldsig#' Id='signature'>
                        <ds:SignedInfo>
                            <ds:CanonicalizationMethod Algorithm='http://www.w3.org/2006/12/xml-c14n11'/>
                            <ds:SignatureMethod Algorithm='http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256'/>
                            <ds:Reference Id='invoiceSignedData' URI=''>
                                <ds:Transforms>
                                    <ds:Transform Algorithm='http://www.w3.org/TR/1999/REC-xpath-19991116'>
                                        <ds:XPath>not(//ancestor-or-self::ext:UBLExtensions)</ds:XPath>
                                    </ds:Transform>
                                    <ds:Transform Algorithm='http://www.w3.org/TR/1999/REC-xpath-19991116'>
                                        <ds:XPath>not(//ancestor-or-self::cac:Signature)</ds:XPath>
                                    </ds:Transform>
                                    <ds:Transform Algorithm='http://www.w3.org/TR/1999/REC-xpath-19991116'>
                                        <ds:XPath>not(//ancestor-or-self::cac:AdditionalDocumentReference[cbc:ID='QR'])</ds:XPath>
                                    </ds:Transform>
                                    <ds:Transform Algorithm='http://www.w3.org/2006/12/xml-c14n11'/>
                                </ds:Transforms>
                                <ds:DigestMethod Algorithm='http://www.w3.org/2001/04/xmlenc#sha256'/>
                                <ds:DigestValue>CAgICAgICAgPC9jYWM6SW52b2ljZUxpbmU+DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9JbnZvaWNlPg==</ds:DigestValue>
                            </ds:Reference>
                            <ds:Reference Type='http://www.w3.org/2000/09/xmldsig#SignatureProperties' URI='#xadesSignedProperties'>
                                <ds:DigestMethod Algorithm='http://www.w3.org/2001/04/xmlenc#sha256'/>
                                <ds:DigestValue>NjY5ZWIzMjg5ZjhlZWY3NjUyNTdkNzFmYmIzMWMwMmQ4OGVkMDgzZWIzMWQwMmYxNGQ4OTMxNDYyMDVlMDkzNA==</ds:DigestValue>
                            </ds:Reference>
                        </ds:SignedInfo>
                        <ds:SignatureValue>MEYCIQCPhRxAvaN69JA9Ng+twhxmpSZ3aQMkOR0p1LKZGZfwtQIhAO6yPeKAGn9slyDkhkJVOt7HEG2jObxsSiGCUGQ0Mb1l</ds:SignatureValue>
                        <ds:KeyInfo>
                            <ds:X509Data>
                                <ds:X509Certificate>yNhycQ3bNlLFdOPlqYT6RVQTWgnK1Gh0NHdcSY4PfC0CIQCSAthXvv7tetUL69Wjp8BxnLLMwerxZhBnewo/gF3EJA==</ds:X509Certificate>
                            </ds:X509Data>
                        </ds:KeyInfo>
                        <ds:Object>
                            <xades:QualifyingProperties xmlns:xades='http://uri.etsi.org/01903/v1.3.2#' Target='signature'>
                                <xades:SignedProperties Id='xadesSignedProperties'>
                                    <xades:SignedSignatureProperties>
                                        <xades:SigningTime>2023-12-26T19:49:21Z</xades:SigningTime>
                                        <xades:SigningCertificate>
                                            <xades:Cert>
                                                <xades:CertDigest>
                                                    <ds:DigestMethod Algorithm='http://www.w3.org/2001/04/xmlenc#sha256'/>
                                                    <ds:DigestValue>YjcyNzI4NWZiN2FlNzI1NTQxOGIzZGY1ZWY4MDc2N2JkMDIyMDM5ZDU5YjJmNWRkOTQ5YTZkMDU2YjEzYzJkZA==</ds:DigestValue>
                                                </xades:CertDigest>
                                                <xades:IssuerSerial>
                                                    <ds:X509IssuerName>CN=TSZEINVOICE-SubCA-1, DC=extgazt, DC=gov, DC=local</ds:X509IssuerName>
                                                    <ds:X509SerialNumber>2475382886904809774818644480820936050208702411</ds:X509SerialNumber>
                                                </xades:IssuerSerial>
                                            </xades:Cert>
                                        </xades:SigningCertificate>
                                    </xades:SignedSignatureProperties>
                                </xades:SignedProperties>
                            </xades:QualifyingProperties>
                        </ds:Object>
                    </ds:Signature>
                </sac:SignatureInformation>
            </sig:UBLDocumentSignatures>
        </ext:ExtensionContent>
    </ext:UBLExtension>
</ext:UBLExtensions>
    <cbc:ProfileID>reporting:1.0</cbc:ProfileID>
    <cbc:ID>3333</cbc:ID>
    <cbc:UUID>feab5f74-ca2d-4047-b421-15907e1ec212</cbc:UUID>
    <cbc:IssueDate>2023-07-06</cbc:IssueDate>
    <cbc:IssueTime>07:17:26</cbc:IssueTime>
    <cbc:InvoiceTypeCode name='0100000'>388</cbc:InvoiceTypeCode>
    <cbc:DocumentCurrencyCode>SAR</cbc:DocumentCurrencyCode>
    <cbc:TaxCurrencyCode>SAR</cbc:TaxCurrencyCode>
    <cac:AdditionalDocumentReference>
        <cbc:ID>ICV</cbc:ID>
        <cbc:UUID>23</cbc:UUID>
    </cac:AdditionalDocumentReference>
    <cac:AdditionalDocumentReference>
        <cbc:ID>PIH</cbc:ID>
        <cac:Attachment>
            <cbc:EmbeddedDocumentBinaryObject mimeCode='text/plain'>NWZlY2ViNjZmZmM4NmYzOGQ5NTI3ODZjNmQ2OTZjNzljMmRiYzIzOWRkNGU5MWI0NjcyOWQ3M2EyN2ZiNTdlOQ==</cbc:EmbeddedDocumentBinaryObject>
        </cac:Attachment>
    </cac:AdditionalDocumentReference>  
    <cac:AdditionalDocumentReference>
        <cbc:ID>QR</cbc:ID>
        <cac:Attachment>
            <cbc:EmbeddedDocumentBinaryObject mimeCode="text/plain">SDFWEsdf234SDFWER</cbc:EmbeddedDocumentBinaryObject>
        </cac:Attachment>
    </cac:AdditionalDocumentReference>
    <cac:Signature>
      <cbc:ID>urn:oasis:names:specification:ubl:signature:Invoice</cbc:ID>
      <cbc:SignatureMethod>urn:oasis:names:specification:ubl:dsig:enveloped:xades</cbc:SignatureMethod>
    </cac:Signature>
    <cac:AccountingSupplierParty>
        <cac:Party>
            <cac:PartyIdentification>
                <cbc:ID schemeID='CRN'></cbc:ID>
            </cac:PartyIdentification>
            <cac:PostalAddress>
                <cbc:StreetName>dsf</cbc:StreetName>
                <cbc:BuildingNumber>3453</cbc:BuildingNumber>
                <cbc:CitySubdivisionName>xcvcx</cbc:CitySubdivisionName>
                <cbc:CityName>xcvxc</cbc:CityName>
                <cbc:PostalZone>45354</cbc:PostalZone>
                <cac:Country>
                    <cbc:IdentificationCode>SA</cbc:IdentificationCode>
                </cac:Country>
            </cac:PostalAddress>
            <cac:PartyTaxScheme>
                <cbc:CompanyID>311380797100003</cbc:CompanyID>
                <cac:TaxScheme>
                    <cbc:ID>VAT</cbc:ID>
                </cac:TaxScheme>
            </cac:PartyTaxScheme>
            <cac:PartyLegalEntity>
                <cbc:RegistrationName>LAMARA SUPERMARKET</cbc:RegistrationName>
            </cac:PartyLegalEntity>
        </cac:Party>
    </cac:AccountingSupplierParty>
    <cac:AccountingCustomerParty>
        <cac:Party>
            <cac:PartyIdentification>
                <cbc:ID schemeID='NAT'></cbc:ID>
            </cac:PartyIdentification>
            <cac:PostalAddress>
                <cbc:StreetName>ddd</cbc:StreetName>
                <cbc:BuildingNumber></cbc:BuildingNumber>
                <cbc:CitySubdivisionName>sss</cbc:CitySubdivisionName>
                <cbc:CityName>vvv</cbc:CityName>
                <cbc:PostalZone>55443</cbc:PostalZone>
                <cac:Country>
                    <cbc:IdentificationCode>SA</cbc:IdentificationCode>
                </cac:Country>
            </cac:PostalAddress>
            <cac:PartyTaxScheme>
                <cbc:CompanyID>311380797200003</cbc:CompanyID>
                <cac:TaxScheme>
                    <cbc:ID>VAT</cbc:ID>
                </cac:TaxScheme>
            </cac:PartyTaxScheme>
            <cac:PartyLegalEntity>
                <cbc:RegistrationName>MESS EXPENSE</cbc:RegistrationName>
            </cac:PartyLegalEntity>
        </cac:Party>
    </cac:AccountingCustomerParty>
    <cac:Delivery>
        <cbc:ActualDeliveryDate>2023-07-06</cbc:ActualDeliveryDate>
    </cac:Delivery>
    <cac:PaymentMeans>
        <cbc:PaymentMeansCode>30</cbc:PaymentMeansCode>
    </cac:PaymentMeans>
    <cac:AllowanceCharge>
        <cbc:ChargeIndicator>false</cbc:ChargeIndicator>
        <cbc:AllowanceChargeReason>discount</cbc:AllowanceChargeReason>
        <cbc:Amount currencyID='SAR'>0.00</cbc:Amount>
        <cac:TaxCategory>
            <cbc:ID schemeID='UN/ECE 5305' schemeAgencyID='6'>S</cbc:ID>
            <cbc:Percent>15</cbc:Percent>
            <cac:TaxScheme>
            <cbc:ID schemeID='UN/ECE 5153' schemeAgencyID='6'>VAT</cbc:ID>
            </cac:TaxScheme>
        </cac:TaxCategory>
    </cac:AllowanceCharge>
    <cac:TaxTotal>
        <cbc:TaxAmount currencyID='SAR'>17.71</cbc:TaxAmount>
    </cac:TaxTotal>
    <cac:TaxTotal>
        <cbc:TaxAmount currencyID='SAR'>17.71</cbc:TaxAmount>
        <cac:TaxSubtotal>
            <cbc:TaxableAmount currencyID='SAR'>118.04</cbc:TaxableAmount>
            <cbc:TaxAmount currencyID='SAR'>17.71</cbc:TaxAmount>
            <cac:TaxCategory>
            <cbc:ID schemeID='UN/ECE 5305' schemeAgencyID='6'>S</cbc:ID>
            <cbc:Percent>15.00</cbc:Percent>
            <cac:TaxScheme>
                <cbc:ID schemeID='UN/ECE 5153' schemeAgencyID='6'>VAT</cbc:ID>
            </cac:TaxScheme>
            </cac:TaxCategory>
        </cac:TaxSubtotal>
    </cac:TaxTotal>
    <cac:LegalMonetaryTotal>
        <cbc:LineExtensionAmount currencyID='SAR'>118.04</cbc:LineExtensionAmount>
        <cbc:TaxExclusiveAmount currencyID='SAR'>118.04</cbc:TaxExclusiveAmount>
        <cbc:TaxInclusiveAmount currencyID='SAR'>135.75</cbc:TaxInclusiveAmount>
        <cbc:AllowanceTotalAmount currencyID='SAR'>0.00</cbc:AllowanceTotalAmount>
        <cbc:PrepaidAmount currencyID='SAR'>0.00</cbc:PrepaidAmount>
        <cbc:PayableAmount currencyID='SAR'>135.75</cbc:PayableAmount>
    </cac:LegalMonetaryTotal>
    <cac:InvoiceLine>
        <cbc:ID>1</cbc:ID>
        <cbc:InvoicedQuantity unitCode='PCE'>1.00</cbc:InvoicedQuantity>
        <cbc:LineExtensionAmount currencyID='SAR'>5.00</cbc:LineExtensionAmount>
        <cac:TaxTotal>
            <cbc:TaxAmount currencyID='SAR'>0.75</cbc:TaxAmount>
            <cbc:RoundingAmount currencyID='SAR'>5.75</cbc:RoundingAmount>
        </cac:TaxTotal>
        <cac:Item>
            <cbc:Name>sdfds</cbc:Name>
            <cac:ClassifiedTaxCategory>
                <cbc:ID>S</cbc:ID>
                <cbc:Percent>15</cbc:Percent>
                <cac:TaxScheme>
                    <cbc:ID>VAT</cbc:ID>
                </cac:TaxScheme>
            </cac:ClassifiedTaxCategory>
        </cac:Item>
        <cac:Price>
            <cbc:PriceAmount currencyID='SAR'>5.00</cbc:PriceAmount>
            <cac:AllowanceCharge>
                <cbc:ChargeIndicator>false</cbc:ChargeIndicator>
                <cbc:AllowanceChargeReason>discount</cbc:AllowanceChargeReason>
                <cbc:Amount currencyID='SAR'>0.00</cbc:Amount>
            </cac:AllowanceCharge>
        </cac:Price>
    </cac:InvoiceLine><cac:InvoiceLine>
        <cbc:ID>2</cbc:ID>
        <cbc:InvoicedQuantity unitCode='PCE'>1.00</cbc:InvoicedQuantity>
        <cbc:LineExtensionAmount currencyID='SAR'>113.04</cbc:LineExtensionAmount>
        <cac:TaxTotal>
            <cbc:TaxAmount currencyID='SAR'>16.96</cbc:TaxAmount>
            <cbc:RoundingAmount currencyID='SAR'>130.00</cbc:RoundingAmount>
        </cac:TaxTotal>
        <cac:Item>
            <cbc:Name>eeee</cbc:Name>
            <cac:ClassifiedTaxCategory>
                <cbc:ID>S</cbc:ID>
                <cbc:Percent>15</cbc:Percent>
                <cac:TaxScheme>
                    <cbc:ID>VAT</cbc:ID>
                </cac:TaxScheme>
            </cac:ClassifiedTaxCategory>
        </cac:Item>
        <cac:Price>
            <cbc:PriceAmount currencyID='SAR'>113.04</cbc:PriceAmount>
            <cac:AllowanceCharge>
                <cbc:ChargeIndicator>false</cbc:ChargeIndicator>
                <cbc:AllowanceChargeReason>discount</cbc:AllowanceChargeReason>
                <cbc:Amount currencyID='SAR'>0.00</cbc:Amount>
            </cac:AllowanceCharge>
        </cac:Price>
    </cac:InvoiceLine>
</Invoice>

From this XML I would like to update value of XML element:

<cac:AdditionalDocumentReference>
    <cbc:ID>QR</cbc:ID>
    <cac:Attachment>
        <cbc:EmbeddedDocumentBinaryObject mimeCode="text/plain">SDFWEsdf234SDFWER</cbc:EmbeddedDocumentBinaryObject>
    </cac:Attachment>
</cac:AdditionalDocumentReference>

I want to change the value of the EmbeddedDocumentBinaryObject element with C#.

What I tried :

XDocument xdoc = XDocument.Load(Server.MapPath("~/XML/EInvoice.xml"));
XNamespace ns = "urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2";                       

xdoc.Descendants(ns + "ProfileID").FirstOrDefault()?.SetValue("sdfwer");

With the above code I can update value of ProfileID element. Is there any way to use this method to obtain my above requirement. I tried different previous questions, but couldn't obtain the exact options. I am a beginner in dealing with XML.


Solution

  • Your <cbc:EmbeddedDocumentBinaryObject> element is in the namespace corresponding to the cbc prefix:

    <Invoice 
      xmlns='urn:oasis:names:specification:ubl:schema:xsd:Invoice-2' 
      xmlns:cac='urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2' 
      xmlns:cbc='urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2' 
      xmlns:ext='urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2'>
    

    Therefore you must search for it in that namespace:

    byte [] binaryValue = Enumerable.Range(0, 773).Select(i => (byte)i).ToArray(); // Replace with your actual binary value
    
    XNamespace cbc = "urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2";
    var embeddedDocumentBinaryObject = xdoc.Descendants(cbc + "EmbeddedDocumentBinaryObject").FirstOrDefault();
    if (embeddedDocumentBinaryObject != null)
        embeddedDocumentBinaryObject.SetValue(Convert.ToBase64String(binaryValue));
    

    That being said, your XML document is fairly large, and you are searching for <cbc:EmbeddedDocumentBinaryObject> elements throughout the entire document. If you would like to reduce the scope to just the specific <cbc:EmbeddedDocumentBinaryObject> with the path shown in your XML and <cbc:ID> value of PIH, you may do so as follows:

    byte [] binaryValue = Enumerable.Range(0, 773).Select(i => (byte)i).ToArray(); // Replace with your actual binary value
    string id = "PIH";
    
    XNamespace @default = "urn:oasis:names:specification:ubl:schema:xsd:Invoice-2";
    XNamespace cac = "urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2";
    XNamespace cbc = "urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2";
    XNamespace ext = "urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2";
    var embeddedDocumentBinaryObject = xdoc
        .Element(@default + "Invoice")                  // <Invoice ...>
        .Elements(cac + "AdditionalDocumentReference")  // <cac:AdditionalDocumentReference>
        .Where(a => a.Element(cbc + "ID")?.Value == id)
        .Elements(cac + "Attachment")                   // <cac:Attachment>
        .Elements(cbc + "EmbeddedDocumentBinaryObject") // <cbc:EmbeddedDocumentBinaryObject ...>
        .FirstOrDefault();
    if (embeddedDocumentBinaryObject != null)
        embeddedDocumentBinaryObject.SetValue(Convert.ToBase64String(binaryValue));
    

    Demo fiddle here.