Select to view content in your preferred language

Publish a Map Image Layer with Feature Service Enabled - Feature Layer Not Nested - Using arcpy

787
1
10-20-2023 12:37 AM
MatthewGeorge
Frequent Contributor

Is it possible to publish a single layer programmatically so that it is not nested in it's Feature Service. When I publish a layer using the below script and I add the resulting Feature Service to Pro from Portal, it adds as a nested layer - My Layer\My Layer - but if you publish a Layer using the normal workflow from Pro by right clicking the Layer in the contents pane and selecting Sharing > Share As Web Layer, adding it to the project will only add the inner layer, not the nested layer.

Not sure if that makes sense but can try explain more clearly if required. Following screenshots might help to clarify as well.

MatthewGeorge_0-1697975459039.png

I'm using the following code to do the publishing:

 

    aprx = arcpy.mp.ArcGISProject("CURRENT")
    m = aprx.activeMap

    #check that the map is valid
    if m == None:
        utils.logAndNotify(logger, "No Map is currently active", "ERROR")
        return
    
    #get the layer
    lyr = m.listLayers(lyrName)[0]

    #get and set the values in the SD draft
    utils.logAndNotify(logger, "Setting values to use in the SD draft")
    sdd = m.getWebLayerSharingDraft("FEDERATED_SERVER", "MAP_IMAGE", lyrName, lyr)
    sdd.federatedServerUrl = svrDict[db]['server']
    sdd.description = desc
    sdd.tags = tags
    sdd.serverFolder = svrDict[db]['folder']

    #export to SD draft file
    utils.logAndNotify(logger, "Exporting to file")
    sdd.exportToSDDraft(sddFile)

    #read the output xml file
    utils.logAndNotify(logger, "Updating the SDD XML file")
    sddXml = md.parse(sddFile)
    xmlKeys = sddXml.getElementsByTagName("Key")
    xmlValues = sddXml.getElementsByTagName("Value")

    #set sharing settings
    everyone = "false"
    group = "false"

    #set values required
    for i in range(xmlKeys.length):
        if xmlKeys[i].firstChild.nodeValue == "PackageUnderMyOrg":
            xmlValues[i].firstChild.nodeValue = org
        if xmlKeys[i].firstChild.nodeValue == "PackageIsPublic":
            xmlValues[i].firstChild.nodeValue = everyone
        if xmlKeys[i].firstChild.nodeValue == "PackageShareGroups":
            xmlValues[i].firstChild.nodeValue = group
        if xmlKeys[i].firstChild.nodeValue == "CallingContext":
            xmlValues[i].firstChild.nodeValue = "0"
        if xmlKeys[i].firstChild.nodeValue == "useMapServiceLayerID":
            xmlValues[i].firstChild.nodeValue = "true"

    #get the type name nodes
    typeNameNodes = sddXml.getElementsByTagName("TypeName")
    for typeNameNode in typeNameNodes:
        if typeNameNode.firstChild.data != "MapServer":
            continue

        utils.logAndNotify(logger, "Setting MAP SERVER settings")

        #get the parent node
        parentNode = typeNameNode.parentNode
        
        #loop through the first child
        for node1 in parentNode.childNodes:
            if node1.tagName != "Definition":
                continue

            #loop through the second child
            for node2 in node1.childNodes:
                if node2.tagName not in ["Info", "ConfigurationProperties","Props"]:
                    continue

                #loop through third child - property array
                for propArray in node2.childNodes:
                    
                    #set the timezone details
                    if node2.tagName == "ConfigurationProperties":
                        dtPropSet = sddXml.createElement("PropertySetProperty")
                        attr = sddXml.createAttribute("xsi:type")
                        attr.value = "typens:PropertySetProperty"
                        dtPropSet.setAttributeNode(attr)
                        dtKey = sddXml.createElement("Key")
                        txt = sddXml.createTextNode("dateFieldsTimezoneID")
                        dtKey.appendChild(txt)
                        dtPropSet.appendChild(dtKey)
                        dtValue = sddXml.createElement("Value")
                        attr = sddXml.createAttribute("xsi:type")
                        attr.value = "xs:string"
                        dtValue.setAttributeNode(attr)
                        txt = sddXml.createTextNode("W. Australia Standard Time")
                        dtValue.appendChild(txt)
                        dtPropSet.appendChild(dtValue)
                        propArray.appendChild(dtPropSet)

                    #loop through the property array
                    for propSet in propArray.childNodes:

                        #loop through the property set
                        for prop in propSet.childNodes:
                            if prop.tagName == "Key":
                                if prop.firstChild.data == "WebCapabilities":
                                    prop.nextSibling.firstChild.data = "Map,Query,Data"
                                elif prop.firstChild.data == "maxRecordCount":
                                    prop.nextSibling.firstChild.data = f"{maxRecords}"
                                elif prop.firstChild.data in ["MinInstances", "MaxInstances"]:
                                    prop.nextSibling.firstChild.data = f"{minMax}"
                                elif prop.firstChild.data == "provider":
                                    prop.nextSibling.firstChild.data = "DMaps" if instanceType == "SHARED" else "ArcObjects11"
    
    #set the feature service settings
    for typeNameNode in typeNameNodes:
        if typeNameNode.firstChild.data != "FeatureServer":
            continue

        utils.logAndNotify(logger, "Setting FEATURE SERVER settings")

        #get the parent node
        parentNode = typeNameNode.parentNode
        
        #loop through the first child
        for node1 in parentNode.childNodes:
            if node1.tagName not in ["Info", "Enabled", "Props"]:
                continue
            
            #enable the setting
            if node1.tagName == "Enabled":
                node1.firstChild.data = "true"
                continue

            #loop through third child - property array
            for propArray in node1.childNodes:

                #loop through the property array
                for propSet in propArray.childNodes:

                    #loop through the property set
                    for prop in propSet.childNodes:
                        if prop.tagName == "Key":
                            if prop.firstChild.data == "WebCapabilities":
                                prop.nextSibling.firstChild.data = "Query,Sync,Extract"
                            elif prop.firstChild.data == "maxRecordCount":
                                prop.nextSibling.firstChild.data = f"{maxRecords}"

    #output the values
    with open(sddFile, "w") as f:
        sddXml.writexml(f)
    
    #stage service
    utils.logAndNotify(logger, "Staging service")
    arcpy.server.StageService(sddFile, sdFile)

    #share
    utils.logAndNotify(logger, "Pushing to Portal")
    arcpy.server.UploadServiceDefinition(sdFile, svrDict[db]['server'])

 

 

 

 

 

 

 

 

 

Tags (2)
0 Kudos
1 Reply
Chris_Matthews
Emerging Contributor

I've encountered the same problem, did you ever find a solution?

0 Kudos