ArcGIS Blog

Administration

ArcGIS Online

Updating ArcGIS.com Hosted Feature Services with Python

By Kevin Hibma and Jeff Moulds

Note: A this workflow has been updated for ArcGIS 10.2/10.2.1. Please read that post depending on your version. [January 24, 2014]

More organizations are moving towards using ArcGIS.com hosted feature services to serve data. One common task that has become a popular question of late is, “How do I automatically update the data within this hosted service?” For example, your organization may want to push nightly updates to keep synchronized with the daily changes made by your Desktop users. One of the easiest ways this can be done as this blog describes, is by overwriting the feature service completely with an updated one.

The following Python script demonstrates how to:

To get started, copy and paste the code into a script file (.py) on your machine. Update the variables with your service name, path to the MXD and your ArcGIS.com account information. The script will create temporary drafts in the same location you saved the script to. Read the comments in line to customize the script to your needs. Once your script is configured, run it on any machine with Desktop, Engine or Server installed.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import arcpy, os, sys
import xml.dom.minidom as DOM
arcpy.env.overwriteOutput = True
# Update these variables
# The tempPath variable is a relative path which is the same directory
# this script is saved to. You can modify this value to a path on your
# system to hold the temporary files.
serviceName = "importantPoints"
tempPath = sys.path[0]
path2MXD = r"C:\path2MXD\pts.mxd"
userName = " "
passWord = " "
# All paths are built by joining names to the tempPath
SDdraft = os.path.join(tempPath, "tempdraft.sddraft")
newSDdraft = os.path.join(tempPath, "updatedDraft.sddraft")
SD = os.path.join(tempPath, serviceName + ".sd")
arcpy.SignInToPortal_server(userName, passWord, "http://www.arcgis.com/")
mxd = arcpy.mapping.MapDocument(path2MXD)
arcpy.mapping.CreateMapSDDraft(mxd, SDdraft, serviceName, "MY_HOSTED_SERVICES")
# Read the contents of the original SDDraft into an xml parser
doc = DOM.parse(SDdraft)
# The follow 5 code pieces modify the SDDraft from a new MapService
# with caching capabilities to a FeatureService with Query,Create,
# Update,Delete,Uploads,Editing capabilities. The first two code
# pieces handle overwriting an existing service. The last three pieces
# change Map to Feature Service, disable caching and set appropriate
# capabilities. You can customize the capabilities by removing items.
# Note you cannot disable Query from a Feature Service.
tagsType = doc.getElementsByTagName('Type')
for tagType in tagsType:
    if tagType.parentNode.tagName == 'SVCManifest':
        if tagType.hasChildNodes():
            tagType.firstChild.data = "esriServiceDefinitionType_Replacement"
tagsState = doc.getElementsByTagName('State')
for tagState in tagsState:
    if tagState.parentNode.tagName == 'SVCManifest':
        if tagState.hasChildNodes():
            tagState.firstChild.data = "esriSDState_Published"
# Change service type from map service to feature service
typeNames = doc.getElementsByTagName('TypeName')
for typeName in typeNames:
    if typeName.firstChild.data == "MapServer":
        typeName.firstChild.data = "FeatureServer"
#Turn off caching
configProps = doc.getElementsByTagName('ConfigurationProperties')[0]
propArray = configProps.firstChild
propSets = propArray.childNodes
for propSet in propSets:
    keyValues = propSet.childNodes
    for keyValue in keyValues:
        if keyValue.tagName == 'Key':
            if keyValue.firstChild.data == "isCached":
                keyValue.nextSibling.firstChild.data = "false"
#Turn on feature access capabilities
configProps = doc.getElementsByTagName('Info')[0]
propArray = configProps.firstChild
propSets = propArray.childNodes
for propSet in propSets:
    keyValues = propSet.childNodes
    for keyValue in keyValues:
        if keyValue.tagName == 'Key':
            if keyValue.firstChild.data == "WebCapabilities":
                keyValue.nextSibling.firstChild.data = "Query,Create,Update,Delete,Uploads,Editing"
# Write the new draft to disk
f = open(newSDdraft, 'w')
doc.writexml( f )
f.close()
# Analyze the service
analysis = arcpy.mapping.AnalyzeForSD(newSDdraft)
if analysis['errors'] == {}:
    # Stage the service
    arcpy.StageService_server(newSDdraft, SD)
    # Upload the service. The OVERRIDE_DEFINITION parameter allows you to override the
    # sharing properties set in the service definition with new values. In this case,
    # the feature service will be shared to everyone on ArcGIS.com by specifying the
    # SHARE_ONLINE and PUBLIC parameters. Optionally you can share to specific groups
    # using the last parameter, in_groups.
    arcpy.UploadServiceDefinition_server(SD, "My Hosted Services", serviceName,
                                         "", "", "", "", "OVERRIDE_DEFINITION","SHARE_ONLINE",
                                         "PUBLIC","SHARE_ORGANIZATION", "")
    print "Uploaded and overwrote service"
else:
    # If the sddraft analysis contained errors, display them and quit.
    print analysis['errors']

You can take this one step further by creating a scheduled task to run the code nightly. By having an MXD which references geodatabase layers updated throughout the day, the automated task will push those changes up to ArcGIS.com when the task is run.

We will be updating the CreateMapSDDraft help topic with this example. Check it out for numerous other map publishing examples.

Share this article