phpxmlxpathdomxpath

How to get xml node value after registering namespace?


I am trying to get xml node value with xpath query but I am getting no results. I registered namespaces for the xml but there is no way to get the result although when I use http://xpather.com/ with the same query I get the right value. Note when I remove registering namespaces lines I get undefined namespace error.

$digestValueXPath = "//Invoice/ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent/sig:UBLDocumentSignatures/sac:SignatureInformation/ds:Signature/ds:Object/xades:QualifyingProperties/xades:SignedProperties/xades:SignedSignatureProperties/xades:SigningCertificate/xades:Cert/xades:CertDigest/ds:DigestValue";

$xml = new DOMDocument(encoding: 'utf-8');
    $xml->loadXML(str_replace("\r", "", $invoiceXML));
    $xpath = new DOMXPath($xml);

    $xpath->registerNamespace('sig', "urn:oasis:names:specification:ubl:schema:xsd:CommonSignatureComponents-2");
    $xpath->registerNamespace('sac', "urn:oasis:names:specification:ubl:schema:xsd:SignatureAggregateComponents-2");
    $xpath->registerNamespace('sbc', "urn:oasis:names:specification:ubl:schema:xsd:SignatureBasicComponents-2");
    $xpath->registerNamespace('ds', "http://www.w3.org/2000/09/xmldsig#");
    $xpath->registerNamespace('xades', "http://uri.etsi.org/01903/v1.3.2#");
    // dd($digestValueXPath);
    // $canonicalizationInvoiceXML = $xml->C14N();
    // $digestValue = $xml->getElementsByTagNameNS("http://www.w3.org/2000/09/xmldsig#", "ds:DigestValue");
    $digestValue = $xpath->query($digestValueXPath);
    dd($digestValue);
    $digestValue->item(0)->nodeValue = $encodedHashedCert;

and this is the xml file

    <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>
            <!-- Please note that the signature values are sample values only -->
            <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 Id="signature" xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
                        <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>p4VtKWX9+VGndJMdv/7WNu1V4=</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>NzY2MGJkMjc0YTU0OTgzZjM2MzNmIzZjNhNWRiZjU4MTc1OTYyN2IxYg==</ds:DigestValue>
                            </ds:Reference>
                        </ds:SignedInfo>
                        <ds:SignatureValue>MEQCIHBXIaofiuU/2KZxLldH6oETcvT4IhyBJszCxTeaNcAAAiBpRELXsTiiBqFxq/dXfa6hq+7RXC2Le9sK87S8EhiwKw==</ds:SignatureValue>
                        <ds:KeyInfo>
                            <ds:X509Data>
                                <ds:X509Certificate>MIIBsTCCAVYCFCfs84hVGkzmV5naL3A/HWfk3CZ6MAoGCCqGSM49BAMCMFwxDzANBgNVBAMMBkFMQU1BTDELMAkGA1UEBhMCUVQQO9N6MPbMdBcRECB5VctM9uQs6/AiEAqzL4INGoyjdcAg5gNhHnSRyLbnocwUpAx69obSopmuE=</ds:X509Certificate>
                            </ds:X509Data>
                        </ds:KeyInfo>
                        <ds:Object>
                            <xades:QualifyingProperties Target="signature" xmlns:xades="http://uri.etsi.org/01903/v1.3.2#">
                                <xades:SignedProperties Id="xadesSignedProperties">
                                    <xades:SignedSignatureProperties>
                                        <xades:SigningTime>2023-07-10T10:19:34Z</xades:SigningTime>
                                        <xades:SigningCertificate>
                                            <xades:Cert>
                                                <xades:CertDigest>
                                                    <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
                                                    <ds:DigestValue>NDg2OTk1NjVlOWNlMmQwMTQ4YmNhYTcMDBmNWQ1NTNiMTg3YThjMDg1N2ZiODYyZQ==</ds:DigestValue>
                                                </xades:CertDigest>
                                                <xades:IssuerSerial>
                                                    <ds:X509IssuerName>L</ds:X509IssuerName>
                                                    <ds:X509SerialNumber>22793452360720868986</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>
</Invoice>

Update: When using this expression it is working

private $digestValueXPath = "/*/*[name()='ext:UBLExtensions']/*[name()='ext:UBLExtension']/*[name()='ext:ExtensionContent']/*[name()='sig:UBLDocumentSignatures']/*[name()='sac:SignatureInformation']/*[name()='ds:Signature']/*[name()='ds:Object']/*[name()='xades:QualifyingProperties']/*[name()='xades:SignedProperties']/*[name()='xades:SignedSignatureProperties']/*[name()='xades:SigningCertificate']/*[name()='xades:Cert']/*[name()='xades:CertDigest']/*[name()='ds:DigestValue']";

Solution

  • You Invoice is also in a namespace: xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2"

    Just add that also with some prefix like this:

    $xpath->registerNamespace('default-ns', "urn:oasis:names:specification:ubl:schema:xsd:Invoice-2");
    

    And than change your XPath to:

    $digestValueXPath = "//default-ns:Invoice/ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent/sig:UBLDocumentSignatures/sac:SignatureInformation/ds:Signature/ds:Object/xades:QualifyingProperties/xades:SignedProperties/xades:SignedSignatureProperties/xades:SigningCertificate/xades:Cert/xades:CertDigest/ds:DigestValue";