Search code examples
xmlazureforeachazure-logic-apps

Azure Logic App: Why is For-Each-Loop for iterationg over XML is not entered?


I have an Azure Logic app and want to access a blob storage via the http-connector. (I know that there are dedicated blob-connectors but I can't use them).

The result of my http call to get a list of files looks like this:

{
    "body": {
        "$content": "77u/PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz48.............",
        "$content-type": "application/xml"
    },
    "headers": {
        "Content-Length": "2198313",
        "Content-Type": "application/xml",
        "Date": "Wed, 11 Oct 2023 14:50:46 GMT",
        "Server": "Windows-Azure-Blob/1.0,Microsoft-HTTPAPI/2.0",
        "Transfer-Encoding": "chunked",
        "x-ms-client-request-id": "XXXXXXXX-ca8b-4876-8369-eff99d9fe0c3",
        "x-ms-request-id": "XXXXXXX-801e-005d-2d52-fc4b85000000",
        "x-ms-version": "2020-04-08"
    },
    "statusCode": 200
}

Inside the content field is a base64 encoded XML file which looks like this.

<?xml version=\"1.0\" encoding=\"utf-8\"?>
<EnumerationResults ServiceEndpoint=\"https://myblob.blob.core.windows.net/\" ContainerName=\"landing\">
    <Blobs>
        <Blob>
            <Name>log.txt</Name>
            <Properties>
                <Creation-Time>Wed, 10 Aug 2022 11:13:23 GMT</Creation-Time>
                <Last-Modified>Wed, 10 Aug 2022 11:13:23 GMT</Last-Modified>
                <Etag>0x8DA7AC15724FC84</Etag>
                <Content-Length>0</Content-Length>
                <Content-Type>application/octet-stream</Content-Type>
                <Content-Encoding/>
                <Content-Language/>
                <Content-CRC64>AAAAAAAAAAA=</Content-CRC64>
                <Content-MD5/>
                <Cache-Control/>
                <Content-Disposition/>
                <BlobType>BlockBlob</BlobType>
                <AccessTier>Hot</AccessTier>
                <AccessTierInferred>true</AccessTierInferred>
                <LeaseStatus>unlocked</LeaseStatus>
                <LeaseState>available</LeaseState>
                <ServerEncrypted>true</ServerEncrypted>
            </Properties>
            <OrMetadata/>
        </Blob>
        <Blob>
            <Name>test.txt</Name>
            <Properties>
                <Creation-Time>Fri, 08 Sep 2023 09:26:20 GMT</Creation-Time>
                <Last-Modified>Fri, 08 Sep 2023 09:26:20 GMT</Last-Modified>
                <Etag>0x8DBB04DA9A2ED71</Etag>
                <Content-Length>0</Content-Length>
                <Content-Type>application/octet-stream</Content-Type>
                <Content-Encoding/>
                <Content-Language/>
                <Content-CRC64>AAAAAAAAAAA=</Content-CRC64>
                <Content-MD5/>
                <Cache-Control/>
                <Content-Disposition/>
                <BlobType>BlockBlob</BlobType>
                <AccessTier>Hot</AccessTier>
                <AccessTierInferred>true</AccessTierInferred>
                <LeaseStatus>unlocked</LeaseStatus>
                <LeaseState>available</LeaseState>
                <ServerEncrypted>true</ServerEncrypted>
            </Properties>
            <OrMetadata/>
        </Blob>
        ....
        ...
        ..
        .
        </Blobs>
        </EnumerationResults>
    
    

Now I want to iterate over every blob to gather the name and Last-Modified. Therefore I set up two nested for-each loops with an xpath expression.

If I take a look at the run history of my workflow the result is failed and it seems that my for-each loop is never entered.

enter image description here

My first for-each expression looks like this:

xpath(xml(variables('Body')),'EnumerationResults/Blobs')

The second one:

xpath(xml(items('For_each')),'Blobs/Blob')

What could be the reason, why my loops are not working?


Solution

  • I am able to get the blob name and Last-Modified date in the following way-

    Workflow-

    enter image description here

    Code-

    {
        "definition": {
            "$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#",
            "actions": {
                "For_each": {
                    "actions": {
                        "For_each_1": {
                            "actions": {
                                "Set_variable": {
                                    "inputs": {
                                        "name": "Name",
                                        "value": "@{xpath(xml(items('For_each_1')),'Blob/Name/text()')[0]}"
                                    },
                                    "type": "SetVariable"
                                },
                                "Set_variable_1": {
                                    "inputs": {
                                        "name": "Last-Modified",
                                        "value": "@{xpath(xml(items('For_each_1')),'Blob/Properties/Last-Modified/text()')[0]}"
                                    },
                                    "runAfter": {
                                        "Set_variable": [
                                            "SUCCEEDED"
                                        ]
                                    },
                                    "type": "SetVariable"
                                }
                            },
                            "foreach": "@xpath(xml(items('For_each')),'Blobs/Blob')",
                            "type": "Foreach"
                        }
                    },
                    "foreach": "@xpath(xml(triggerbody()),'EnumerationResults/Blobs')",
                    "runAfter": {
                        "Last-Modified": [
                            "SUCCEEDED"
                        ]
                    },
                    "type": "Foreach"
                },
                "Last-Modified": {
                    "inputs": {
                        "variables": [
                            {
                            "name": "Last-Modified",
                                "type": "string"
                            }
                        ]
                    },
                    "runAfter": {
                        "Name": [
                            "SUCCEEDED"
                        ]
                    },
                    "type": "InitializeVariable"
                },
                "Name": {
                    "inputs": {
                        "variables": [
                            {
                            "name": "Name",
                                "type": "string"
                            }
                        ]
                    },
                    "runAfter": { },
                    "type": "InitializeVariable"
                }
            },
            "contentVersion": "1.0.0.0",
            "outputs": { },
            "triggers": {
                "HTTP": {
                    "inputs": {
                        "method": "GET",
                        "uri": "https://afreenstorage12.blob.core.windows.net/demo?restype=container&comp=list&sv=2022-11-02&ss=bfqt&srt=sco&sp=yyyyy&se=2023-10-26T20:08:12Z&st=2023-10-26T12:08:12Z&spr=https&sig=***********"
                    },
                    "recurrence": {
                        "frequency": "Minute",
                        "interval": 3
                    },
                    "type": "Http"
                }
            }
        },
        "kind": "Stateful"
    }
    

    First For_each loop-

    xpath(xml(triggerbody()),'EnumerationResults/Blobs')

    enter image description here

    Second For_each loop-

    xpath(xml(items('For_each')),'Blobs/Blob')

    enter image description here

    Output-

    enter image description here

    You can follow my approach to get the blob name and Last-Modified date.