diff --git a/.github/actions/publish_docker_image/action.yml b/.github/actions/publish_docker_image/action.yml
index 1a8bad7..c21be74 100644
--- a/.github/actions/publish_docker_image/action.yml
+++ b/.github/actions/publish_docker_image/action.yml
@@ -16,8 +16,6 @@ runs:
       with:
         images: |
           axiom/docker-erddap
-        flavor: |
-          suffix=-jdk21-openjdk,onlatest=true
         tags: |
           type=raw,value=latest,enable={{is_default_branch}}
           type=ref,event=tag
diff --git a/Dockerfile b/Dockerfile
index 8fb6f4b..15faee0 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,100 +1,58 @@
-ARG BASE_IMAGE=tomcat:10.1.26-jdk21-temurin-jammy
-#referencing a specific image digest pins our unidata tomcat-docker image to platform amd64 (good)
-ARG UNIDATA_TOMCAT_IMAGE=unidata/tomcat-docker:10-jdk17@sha256:af7d3fecec753cbd438f25881deeaf48b40ac1f105971d6f300252e104e39fb2
-FROM ${UNIDATA_TOMCAT_IMAGE} AS unidata-tomcat-image
-FROM ${BASE_IMAGE}
+ARG ERDDAP_VERSION=v2.27.0
+ARG BASE_IMAGE=erddap/erddap:$ERDDAP_VERSION
+FROM $BASE_IMAGE
 
-#use approaches and hardened files from https://github.com/Unidata/tomcat-docker
-#note: we don't inherit directly from Unidata/tomcat-docker to allow more
-#flexibility in building images using different tomcat base images, architectures, etc
-RUN apt-get update && \
-    apt-get install -y --no-install-recommends  \
-        gosu \
-        zip \
-        unzip \
-        && \
-    # Cleanup
-    apt-get clean && \
-    rm -rf /var/lib/apt/lists/* && \
-    # Eliminate default web applications
-    rm -rf ${CATALINA_HOME}/webapps/* && \
-    rm -rf ${CATALINA_HOME}/webapps.dist && \
-    # Obscuring server info
-    cd ${CATALINA_HOME}/lib && \
-    mkdir -p org/apache/catalina/util/ && \
-    unzip -j catalina.jar org/apache/catalina/util/ServerInfo.properties \
-        -d org/apache/catalina/util/ && \
-    sed -i 's/server.info=.*/server.info=Apache Tomcat/g' \
-        org/apache/catalina/util/ServerInfo.properties && \
-    zip -ur catalina.jar \
-        org/apache/catalina/util/ServerInfo.properties && \
-    rm -rf org && cd ${CATALINA_HOME} && \
-    # Setting restrictive umask container-wide
-    echo "session optional pam_umask.so" >> /etc/pam.d/common-session && \
-    sed -i 's/UMASK.*022/UMASK           007/g' /etc/login.defs
-
-# Security enhanced web.xml
-COPY --from=unidata-tomcat-image ${CATALINA_HOME}/conf/web.xml ${CATALINA_HOME}/conf/
-
-# Security enhanced server.xml
-COPY --from=unidata-tomcat-image ${CATALINA_HOME}/conf/server.xml ${CATALINA_HOME}/conf/
-
-ARG ERDDAP_VERSION=2.25.1
-ARG ERDDAP_CONTENT_VERSION=1.0.0
-ARG ERDDAP_WAR_URL="https://github.com/ERDDAP/erddap/releases/download/v${ERDDAP_VERSION}/erddap.war"
-ARG ERDDAP_CONTENT_URL="https://github.com/ERDDAP/erddapContent/archive/refs/tags/content${ERDDAP_CONTENT_VERSION}.zip"
-ENV ERDDAP_bigParentDirectory=/erddapData
-
-RUN apt-get update && apt-get install -y unzip xmlstarlet \
-    && if ! command -v gosu &> /dev/null; then apt-get install -y gosu; fi \
+RUN apt-get update && apt-get install -y gettext-base xmlstarlet \
     && rm -rf /var/lib/apt/lists/*
 
-ARG BUST_CACHE=1
-RUN \
-    mkdir -p /tmp/dl && \
-    curl -fSL "${ERDDAP_WAR_URL}" -o /tmp/dl/erddap.war && \
-    unzip /tmp/dl/erddap.war -d ${CATALINA_HOME}/webapps/erddap/ && \
-    curl -fSL "${ERDDAP_CONTENT_URL}" -o /tmp/dl/erddapContent.zip && \
-    unzip /tmp/dl/erddapContent.zip -d /tmp/dl/erddapContent && \
-    find /tmp/dl/erddapContent -type d -name content -exec cp -r "{}" ${CATALINA_HOME} \; && \
-    rm -rf /tmp/dl && \
-    sed -i 's##\n' ${CATALINA_HOME}/conf/context.xml && \
-    rm -rf /tmp/* /var/tmp/* && \
-    mkdir -p ${ERDDAP_bigParentDirectory}
-
-# Java options
-COPY files/setenv.sh ${CATALINA_HOME}/bin/setenv.sh
-
-# server.xml fixup
-COPY update-server-xml.sh /opt/update-server-xml.sh
-RUN /opt/update-server-xml.sh
-
-# Default configuration
-# Note: Make sure ERDDAP_flagKeyKey is set either in a runtime environment variable or in setup.xml
-#       If a value is not set, a random value for ERDDAP_flagKeyKey will be generated at runtime.
-ENV ERDDAP_baseHttpsUrl="https://localhost:8443" \
-    ERDDAP_emailEverythingTo="nobody@example.com" \
-    ERDDAP_emailDailyReportsTo="nobody@example.com" \
-    ERDDAP_emailFromAddress="nothing@example.com" \
-    ERDDAP_emailUserName="" \
-    ERDDAP_emailPassword="" \
-    ERDDAP_emailProperties="" \
-    ERDDAP_emailSmtpHost="" \
-    ERDDAP_emailSmtpPort="" \
-    ERDDAP_adminInstitution="Axiom Docker Install" \
-    ERDDAP_adminInstitutionUrl="https://github.com/axiom-data-science/docker-erddap" \
-    ERDDAP_adminIndividualName="Axiom Docker Install" \
-    ERDDAP_adminPosition="Software Engineer" \
-    ERDDAP_adminPhone="555-555-5555" \
-    ERDDAP_adminAddress="123 Irrelevant St." \
-    ERDDAP_adminCity="Nowhere" \
-    ERDDAP_adminStateOrProvince="AK" \
-    ERDDAP_adminPostalCode="99504" \
-    ERDDAP_adminCountry="USA" \
-    ERDDAP_adminEmail="nobody@example.com"
-
-COPY entrypoint.sh datasets.d.sh /
-ENTRYPOINT ["/entrypoint.sh"]
-
-EXPOSE 8080
-CMD ["catalina.sh", "run"]
+COPY datasets.d.sh /
+
+# advise users to use upstream offical ERDDAP docker image
+# if they aren't using experimental features in this image
+COPY --chmod=755 </dev/null | grep -q "$DATASETS_XML_MD5SUM"; then
+      #we don't have a backup of this version of datasets.xml yet, make one
+      DATASETS_XML_BACKUP="${ERDDAP_CONTENT_DIR}"/datasets.xml.$(date -u +"%Y%m%dT%H%M%SZ").bak
+      echo "Backing up "${DATASETS_XML}" to ${DATASETS_XML_BACKUP}"
+      cp "$DATASETS_XML" "${DATASETS_XML_BACKUP}"
+    fi
+  fi
+  /datasets.d.sh -o "$DATASETS_XML" -w
+fi
+EOF
+
+ENV ERDDAP_useHeadersForUrl=true \
+    ERDDAP_useSaxParser=true
diff --git a/README.md b/README.md
index 4b810b7..1d84c05 100644
--- a/README.md
+++ b/README.md
@@ -1,19 +1,37 @@
 # ERDDAP on Docker
 
-A feature full Tomcat (SSL over APR, etc.) running [ERDDAP](http://coastwatch.pfeg.noaa.gov/erddap/index.html)
+[ERDDAP](http://coastwatch.pfeg.noaa.gov/erddap/index.html) docker image with experimental features (datasets.d, see below).
+
+## Upstream Official ERDDAP Docker Image
+
+As of version v2.27.0 this image (axiom/docker-erddap)
+is derived from the official ERDDAP Docker image (erddap/erddap).
+
+If you are not using any experimental functionality offered
+by the axiom image (notably datasets.d), you are recommended
+to use the official ERDDAP Docker image instead.
+
+See https://hub.docker.com/r/erddap/erddap for more details.
+
+## Versions
 
 Most recent versions:
 
-* `axiom/docker-erddap:latest-jdk21-openjdk` (2.25.1)
+* `axiom/docker-erddap:latest`
+* `axiom/docker-erddap:v2.27.0`
 * `axiom/docker-erddap:2.25.1-jdk21-openjdk`
-* `axiom/docker-erddap:2.24-jdk21-openjdk`
-* `axiom/docker-erddap:2.23-jdk17-openjdk`
 
-See all versions available [here](https://hub.docker.com/r/axiom/docker-erddap/tags). As always, consult the [ERDDAP Changes](https://coastwatch.pfeg.noaa.gov/erddap/download/changes.html) documentation before upgrading your server.
+See all versions available [here](https://hub.docker.com/r/axiom/docker-erddap/tags).
+As always, consult the [ERDDAP Changes](https://coastwatch.pfeg.noaa.gov/erddap/download/changes.html)
+documentation before upgrading your server.
+
+Use any of the `latest-*` images with caution as they follow the upstream image,
+and is not as thoroughly tested as tagged images.
 
-Use any of the `latest-*` images with caution as they follow the upstream image, and is not as thoroughly tested as tagged images.
+## Breaking changes
 
-[Dependabot](https://docs.github.com/en/free-pro-team@latest/github/administering-a-repository/keeping-your-dependencies-updated-automatically) is used to automatically make PRs to update the upstream image ([`.github/dependabot.yml`](.github/dependabot.yml)).
+* v2.27.0
+** CORS is now off by default. To enable it, set `ERDDAP_enableCors=true`.
 
 ## Quickstart
 
@@ -37,7 +55,7 @@ or, generate a basic dataset configuration without input for
 later customization
 
 ```bash
-./make-dataset.xml /path/to/your.csv EDDTableFromAsciiFiles > /path/to/your-dataset.xml
+./make-dataset-xml.sh /path/to/your.csv EDDTableFromAsciiFiles > /path/to/your-dataset.xml
 ```
 
 ## Configuration
@@ -48,10 +66,7 @@ See [these instructions for configuring Tomcat](https://github.com/unidata/tomca
 
 ### CORS
 
-The [Tomcat configuration](https://github.com/unidata/tomcat-docker) used by this image enables the
-[Apache Tomcat CORS filter](https://tomcat.apache.org/tomcat-8.5-doc/config/filter.html#CORS_Filter) by
-default. To disable it (maybe you want to handle CORS uniformly in a proxying webserver?), set environment
-variable `DISABLE_CORS` to `1`.
+CORS is off by default. To enable it, set `ERDDAP_enableCors=true`.
 
 ### ERDDAP
 
@@ -241,6 +256,8 @@ Example:
 ERDDAP_DATASETS_cacheMinutes=20 ./datasets.d.sh -d examples/datasets.d
 ```
 
+As of version v2.27.0 environment variables in the generated datasets.xml file will also be replaced using envsubst.
+
 ##### Elegantly removing datasets in datasets.d mode
 
 ERDDAP has a [specific process](https://coastwatch.pfeg.noaa.gov/erddap/download/setupDatasetsXml.html#active)
diff --git a/datasets.d.sh b/datasets.d.sh
index e215f61..52bf70e 100755
--- a/datasets.d.sh
+++ b/datasets.d.sh
@@ -12,6 +12,8 @@ DATASETSD_OUTPUT_PATH="${DATASETSD_OUTPUT_PATH:-/usr/local/tomcat/content/erddap
 DATASETSD_MARK_REMOVED_DATASETS_INACTIVE="${DATASETSD_MARK_REMOVED_DATASETS_INACTIVE:-0}"
 DATASETSD_WRITE_TO_OUTPUT_PATH="${DATASETSD_WRITE_TO_OUTPUT_PATH:-0}"
 DATASETSD_REFRESH_MISSING_DATASETS="${DATASETSD_REFRESH_MISSING_DATASETS:-0}"
+ERDDAP_bigParentDirectory="${ERDDAP_bigParentDirectory:-/erddapData}"
+
 while getopts ":d:io:rw" opt; do
   case ${opt} in
     d )
@@ -71,18 +73,25 @@ if [ "$DATASETSD_MARK_REMOVED_DATASETS_INACTIVE" == "1" ] && [ -n "$DATASETSD_OU
   true
 fi
 
-#empty edit for formatting
-DXML=$(echo "$DXML" | xmlstarlet edit --inplace)
+#empty edit for formatting, substituting env vars with envsubst
+DXML=$(echo "$DXML" | xmlstarlet edit --inplace | envsubst)
 
 #write output to target file if one was provided and write to stdout flag was not provided
 if [ -n "$DATASETSD_OUTPUT_PATH" ] && [ "$DATASETSD_WRITE_TO_OUTPUT_PATH" == "1" ]; then
   echo "$DXML" > "$DATASETSD_OUTPUT_PATH"
   #set refresh flags for any datasetIDs in datasets.xml that are not in the running ERDDAP config if the refresh option was set
-  if [ -n "$DATASETSD_REFRESH_MISSING_DATASETS" ] && [ "$DATASETSD_REFRESH_MISSING_DATASETS" == "1" ]; then
-    comm -23 \
-      <(xmlstarlet select -t -v "/erddapDatasets/dataset/@datasetID" "$DATASETSD_OUTPUT_PATH" | sort) \
-      <(curl -sS "http://localhost:8080/erddap/tabledap/allDatasets.csv0?datasetID" | grep -v "^allDatasets$" | sort) \
-      | xargs -I{} touch /erddapData/flag/{}
+  #check if erddap is running and /erddapData/flag exists first
+  if [ -n "$DATASETSD_REFRESH_MISSING_DATASETS" ] && [ "$DATASETSD_REFRESH_MISSING_DATASETS" == "1" ] ; then
+    if ! curl -fsS "http://localhost:8080/erddap/index.html" &> /dev/null; then
+      echo "Skipping refresh of missing datasets because ERDDAP isn't running"
+    elif ! [ -d "${ERDDAP_bigParentDirectory}/flag" ]; then
+      echo "Skipping refresh of missing datasets because ${ERDDAP_bigParentDirectory}/flag directory doesn't exist"
+    else
+      comm -23 \
+        <(xmlstarlet select -t -v "/erddapDatasets/dataset/@datasetID" "$DATASETSD_OUTPUT_PATH" | sort) \
+        <(curl -sS "http://localhost:8080/erddap/tabledap/allDatasets.csv0?datasetID" | grep -v "^allDatasets$" | sort) \
+        | xargs -I{} touch "${ERDDAP_bigParentDirectory}"/flag/{}
+    fi
   fi
 else
   echo "$DXML"
diff --git a/entrypoint.sh b/entrypoint.sh
deleted file mode 100755
index 9f6f42f..0000000
--- a/entrypoint.sh
+++ /dev/null
@@ -1,94 +0,0 @@
-#!/bin/bash
-set -e
-
-# preferable to fire up Tomcat via start-tomcat.sh which will start Tomcat with
-# security manager, but inheriting containers can also start Tomcat via
-# catalina.sh
-
-if [ "$1" = 'start-tomcat.sh' ] || [ "$1" = 'catalina.sh' ]; then
-    # generate random flagKeyKey if not set
-    if [ -z "$ERDDAP_flagKeyKey" ] && grep "CHANGE THIS TO YOUR FAVORITE QUOTE" \
-        "${CATALINA_HOME}/content/erddap/setup.xml" &> /dev/null; then
-      echo "flagKeyKey isn't properly set. Generating a random value." >&2
-      export ERDDAP_flagKeyKey=$(cat /proc/sys/kernel/random/uuid)
-    fi
-
-    USER_ID=${TOMCAT_USER_ID:-1000}
-    GROUP_ID=${TOMCAT_GROUP_ID:-1000}
-
-    ###
-    # Tomcat user
-    ###
-    # create group for GROUP_ID if one doesn't already exist
-    if ! getent group $GROUP_ID &> /dev/null; then
-      groupadd -r tomcat -g $GROUP_ID
-    fi
-    # create user for USER_ID if one doesn't already exist
-    if ! getent passwd $USER_ID &> /dev/null; then
-      useradd -u $USER_ID -g $GROUP_ID tomcat
-    fi
-    # alter USER_ID with nologin shell and CATALINA_HOME home directory
-    usermod -d "${CATALINA_HOME}" -s /sbin/nologin $(id -u -n $USER_ID)
-
-    ###
-    # Change CATALINA_HOME ownership to tomcat user and tomcat group
-    # Restrict permissions on conf
-    ###
-
-    chown -R $USER_ID:$GROUP_ID ${CATALINA_HOME} && find ${CATALINA_HOME}/conf \
-        -type d -exec chmod 755 {} \; -o -type f -exec chmod 400 {} \;
-    chown -R $USER_ID:$GROUP_ID /erddapData
-    sync
-
-    ###
-    # Deactivate CORS filter in web.xml if DISABLE_CORS=1
-    # Useful if CORS is handled outside of Tomcat (e.g. in a proxying webserver like nginx)
-    ###
-    if [ "$DISABLE_CORS" == "1" ]; then
-      echo "Deactivating Tomcat CORS filter"
-      xmlstarlet edit --inplace --delete '//_:filter[./_:filter-name = "CorsFilter"]' \
-        --delete '//_:filter-mapping[./_:filter-name = "CorsFilter"]' "${CATALINA_HOME}/conf/web.xml"
-    fi
-
-    ###
-    # Add datasets in /datasets.d to datasets.xml
-    ###
-    if [ -d "/datasets.d" ]; then
-      echo "Creating datasets.xml from /datasets.d"
-      ERDDAP_CONTENT_DIR="/usr/local/tomcat/content/erddap"
-      DATASETS_XML="${ERDDAP_CONTENT_DIR}/datasets.xml"
-      if [ -f "$DATASETS_XML" ]; then
-        #datasets.xml exists, make sure we have a backup of it
-        DATASETS_XML_MD5SUM=$(md5sum "$DATASETS_XML" | awk '{print $1}')
-        if ! md5sum "${ERDDAP_CONTENT_DIR}/datasets.xml.*.bak" 2>/dev/null | grep -q "$DATASETS_XML_MD5SUM"; then
-          #we don't have a backup of this version of datasets.xml yet, make one
-          DATASETS_XML_BACKUP="${ERDDAP_CONTENT_DIR}"/datasets.xml.$(date -u +"%Y%m%dT%H%M%SZ").bak
-          echo "Backing up "${DATASETS_XML}" to ${DATASETS_XML_BACKUP}"
-          cp "$DATASETS_XML" "${DATASETS_XML_BACKUP}"
-        fi
-      fi
-      /datasets.d.sh -o "$DATASETS_XML" -w
-    fi
-
-    ###
-    # Run executables/shell scripts in /init.d on each container startup
-    # Inspired by postgres' /docker-entrypoint-initdb.d
-    # https://github.com/docker-library/docs/blob/master/postgres/README.md#initialization-scripts
-    # https://github.com/docker-library/postgres/blob/master/docker-entrypoint.sh#L156
-    ###
-    if [ -d "/init.d" ]; then
-      for f in /init.d/*; do
-        if [ -x "$f" ]; then
-          echo "Executing $f"
-          "$f"
-        elif [[ $f == *.sh ]]; then
-          echo "Sourcing $f (not executable)"
-          . "$f"
-        fi
-      done
-    fi
-
-    exec gosu $USER_ID "$@"
-fi
-
-exec "$@"
diff --git a/examples/datasets.d/trees.csv.xml b/examples/datasets.d/trees.csv.xml
index 9dad79c..12f4ae8 100644
--- a/examples/datasets.d/trees.csv.xml
+++ b/examples/datasets.d/trees.csv.xml
@@ -1,4 +1,4 @@
-
+
   10080
   10000
   /data/
diff --git a/examples/docker-compose.yml b/examples/docker-compose.yml
index 75c7920..19927eb 100644
--- a/examples/docker-compose.yml
+++ b/examples/docker-compose.yml
@@ -8,7 +8,7 @@ services:
       ERDDAP_DATASETS_standardPrivacyPolicy: "Any and all usage of this data is permitted.
"
       DATASETSD_MARK_REMOVED_DATASETS_INACTIVE: "1"
       DATASETSD_REFRESH_MISSING_DATASETS: "1"
-      DISABLE_CORS: "1"
+      TREES_DATASET_NAME: "asdf-trees"
     volumes:
       - ./data:/data:ro
       - ./datasets.d:/datasets.d:ro
diff --git a/files/setenv.sh b/files/setenv.sh
deleted file mode 100755
index 5956d9b..0000000
--- a/files/setenv.sh
+++ /dev/null
@@ -1,42 +0,0 @@
-#!/bin/sh
-
-if [ -f "${CATALINA_HOME}/bin/config.sh" ];
-then
-    set -o allexport
-    source "${CATALINA_HOME}/bin/config.sh"
-    set +o allexport
-fi
-
-ERDDAP_CONFIG=$(env | grep --regexp "^ERDDAP_.*$" | sort)
-if [ -n "$ERDDAP_CONFIG" ]; then
-    echo -e "ERDDAP configured with:\n$ERDDAP_CONFIG"
-fi
-
-JAVA_MAJOR_VERSION=$(java -version 2>&1 | head -1 | cut -d'"' -f2 | sed '/^1\./s///' | cut -d'.' -f1)
-
-# JAVA_OPTS
-NORMAL="-server"
-
-# Memory
-if [ -n "$ERDDAP_MAX_RAM_PERCENTAGE" ]; then
-  JVM_MEMORY_ARGS="-XX:MaxRAMPercentage=${ERDDAP_MAX_RAM_PERCENTAGE}"
-else
-  ERDDAP_MEMORY="${ERDDAP_MEMORY:-4G}"
-  JVM_MEMORY_ARGS="-Xms${ERDDAP_MIN_MEMORY:-${ERDDAP_MEMORY}} -Xmx${ERDDAP_MAX_MEMORY:-${ERDDAP_MEMORY}}"
-fi
-
-HEAP_DUMP="-XX:+HeapDumpOnOutOfMemoryError"
-HEADLESS="-Djava.awt.headless=true"
-
-EXTRAS=${JAVA_EXTRAS:-}
-if [ $JAVA_MAJOR_VERSION -lt 9 ]; then
-  #these options are deprecated in java 9 and illegal in java 14+
-  EXTRAS="$EXTRAS -XX:+UseConcMarkSweepGC -XX:+CMSClassUnloadingEnabled"
-fi
-
-CONTENT_ROOT="-DerddapContentDirectory=$CATALINA_HOME/content/erddap"
-JNA_DIR="-Djna.tmpdir=/tmp/"
-FASTBOOT="-Djava.security.egd=file:/dev/./urandom"
-
-JAVA_OPTS="$JAVA_OPTS $NORMAL $JVM_MEMORY_ARGS $HEAP_DUMP $HEADLESS $EXTRAS $CONTENT_ROOT/ $JNA_DIR $FASTBOOT"
-echo "ERDDAP Running with: $JAVA_OPTS"
diff --git a/make-dataset-xml.sh b/make-dataset-xml.sh
index 745d07b..ff935a8 100755
--- a/make-dataset-xml.sh
+++ b/make-dataset-xml.sh
@@ -20,7 +20,9 @@ DATASET_TYPE=${2:-"EDDTableFromAsciiFiles"}
 TARGET_FILENAME="$(basename ""$TARGET_FILE"")"
 
 docker run --rm -v $(realpath "$TARGET_FILE"):/data_directory/data_file \
-  --workdir /usr/local/tomcat/webapps/erddap/WEB-INF axiom/docker-erddap \
+  --workdir /usr/local/tomcat/webapps/erddap/WEB-INF \
+  -e ERDDAP_flagKeyKey=$(date +%s) \
+  axiom/docker-erddap:latest-jdk21-openjdk \
     bash ./GenerateDatasetsXml.sh ${DATASET_TYPE} /data_directory data_file $(yes '""' | head -n 18) \
   | sed -n '/^&2
-  exit 1
-fi
-
-RELAXED_PATH_CHARS="[]|"
-RELAXED_QUERY_CHARS="[]:|{}^\`"<>"
-
-function set_attribute {
-  ELEM="$1"
-  ATTR="$2"
-  VAL="$3"
-  if [ -z "$(xmlstarlet sel -t -c "${ELEM}[@${ATTR}='${VAL}']" $SERVER_XML)" ]; then
-    #xmlstarlet escapes special characters like & when writing values, and we
-    #want the attributes to be exactly as we define them. insert replacement
-    #target tokens instead, and then replace with sed.
-    #ampersands are also special characters in sed, so replace with ~ first
-    #and then replace again back to &
-    TOKEN="__${ATTR}__"
-    xmlstarlet edit --inplace -P -u "${ELEM}/@${ATTR}" -v "${TOKEN}" \
-      -i "${ELEM}[not(@${ATTR})]" -t attr -n "${ATTR}" -v "${TOKEN}" \
-      $SERVER_XML
-    sed -i -e "s/${TOKEN}/$( echo $VAL | tr '&' '~')/" -e "s/~/\&/g" $SERVER_XML
-  fi
-}
-
-#set Connector relaxedPathChars and relaxedQueryChars to allow DAP queries
-set_attribute /Server/Service/Connector relaxedPathChars "$RELAXED_PATH_CHARS"
-set_attribute /Server/Service/Connector relaxedQueryChars "$RELAXED_QUERY_CHARS"
-
-# Enable request attributes so that, when using a reverse proxy, the original
-# client ip is recorded in logs rather than the internal proxy ip
-set_attribute /Server/Service/Engine/Host/Valve requestAttributesEnable "true"
-
-#create RemoteIpValve if missing. this is needed so ERDDAP knows when its responding to https requests
-#end result should look like:
-#
-#https://stackoverflow.com/a/9172796/193435
-if [ -z "$(xmlstarlet sel -t -c "/Server/Service/Engine/Host/Valve[@className='org.apache.catalina.valves.RemoteIpValve']" $SERVER_XML)" ]; then
-  xmlstarlet edit --inplace -P -s /Server/Service/Engine/Host -t elem -n RemoteIpValve -v "" \
-    -i //RemoteIpValve -t attr -n "className" -v "org.apache.catalina.valves.RemoteIpValve" \
-    -i //RemoteIpValve -t attr -n "remoteIpHeader" -v "X-Forwarded-For" \
-    -i //RemoteIpValve -t attr -n "protocolHeader" -v "X-Forwarded-Proto" \
-    -i //RemoteIpValve -t attr -n "protocolHeaderHttpsValue" -v "https" \
-    -r //RemoteIpValve -v Valve \
-    $SERVER_XML
-fi