<jupyter_start><jupyter_text>List Nodes in the Production EnvironmentConnect to the DataONE production environment, retrieve the list of nodes, and print out the response document.Uses the [`CNCore.listNodes()`](https://dataone-architecture-documentation.readthedocs.io/en/latest/apis/CN_APIs.htmlCNCore.listNodes) API.<jupyter_code># notebook utils contains some convenience methods, see notebook_utils/__init__.py
import notebook_utils as nbu

from d1_client import cnclient_2_0

cn_base_url = nbu.ENVIRONMENTS["production"]
print("Using base url of: {0}\n".format(cn_base_url))

cncli = cnclient_2_0.CoordinatingNodeClient_2_0(base_url=cn_base_url)
nodes = cncli.listNodes()

print("XML Response:")
print(nbu.asXml(nodes, max_lines=40))<jupyter_output>Using base url of: https://cn.dataone.org/cn

XML Response:
<?xml version="1.0" ?>
<ns1:nodeList xmlns:ns1="http://ns.dataone.org/service/types/v2.0">
  <node replicate="false" state="up" synchronize="false" type="cn">
    <identifier>urn:node:CN</identifier>
    <name>cn</name>
    <description>Round Robin Router for Production Coordinating Nodes</description>
    <baseURL>https://cn.dataone.org/cn</baseURL>
    <services>
      <service available="true" name="CNCore" version="v1"/>
      <service available="true" name="CNRead" version="v1"/>
      <service available="true" name="CNAuthorization" version="v1"/>
      <service available="true" name="CNIdentity" version="v1">
        <restriction methodName="mapIdentity">
          <subject>CN=urn:node:KNB,DC=dataone,DC=org</subject>
        </restriction>
      </service>
      <service available="true" name="CNReplication" version="v1"/>
      <service available="true" name="CNRegister" version="v1"/>
      <service available="true" n[...]<jupyter_text>Formatted list of NodesPrint out a formatted list of Member Nodes in the environment<jupyter_code># Print a formatted list of nodes, showing only MNs:
i = 0
for node in nodes.node:
    if node.type.upper() == "MN":
        i += 1
        print(f"{i:02d}: {nbu.propertyStr(node.identifier):25}{node.baseURL:<55}{node.state:<5}{node.name}")<jupyter_output>01: urn:node:KNB             https://knb.ecoinformatics.org/knb/d1/mn               up   KNB Data Repository
02: urn:node:ESA             https://data.esa.org/esa/d1/mn                         up   ESA Data Registry
03: urn:node:SANPARKS        https://dataknp.sanparks.org/sanparks/d1/mn            up   SANParks Data Repository
04: urn:node:ORNLDAAC        http://mercury-ops2.ornl.gov/ornldaac/mn               down ORNL DAAC
05: urn:node:LTER            https://gmn.lternet.edu/mn                             up   U.S. LTER Network
06: urn:node:CDL             https://merritt-aws.cdlib.org:8084/mn                  up   UC3 Merritt
07: urn:node:PISCO           https://data.piscoweb.org/catalog/d1/mn                up   PISCO MN
08: urn:node:ONEShare        https://oneshare.unm.edu/mn                            up   ONEShare DataONE Member Node
09: urn:node:mnORC1          https://mn-orc-1.dataone.org/knb/d1/mn                 up   DataONE ORC Dedicated Replica Server
10: urn:node:mnUNM1  [...]<jupyter_text>Mapping the nodesApproximate locations of the nodes are available in the node document. Making a map of the nodes is straight forward:<jupyter_code>from ipyleaflet import Map, Marker, MarkerCluster

def getCNProperty(node, name):
    #Note: 'property' is a reserved name in Pyxb, so it is renamed to "property_"
    for p in node.property_:
        if p.key == name:
            return p.value()
    return None

m = Map(center=(0, -50), zoom=1)
m.layout.width = "100%"
m.layout.height = "600px"

for node in nodes.node:
    if node.type.upper() == "MN":
        coord = getCNProperty(node, "CN_location_lonlat")
        if coord is not None:
            lon,lat = coord.split(",")
            marker = Marker(location=(lat, lon), title=node.identifier.value(), draggable=False)
            m.add_layer(marker)
m<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.12785159187766357, 'fraction_numerical': 0.0188017046878917, 'mean_word_length': 3.2311770943796394, 'pattern_counts': {'":': 2, '<': 37, '<?xml version=': 1, '>': 34, 'https://': 11, 'lorem ipsum': 0, 'www.': 0, 'xml': 2}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '3', 'dir': 'jupyter-structured-clean-dedup', 'id': '454833', 'license': 'Apache-2.0', 'n_tokens_mistral': 1365, 'n_tokens_neox': 1323, 'n_words': 300, 'path': 'python_examples/02_listNodes.ipynb', 'repo_name': 'DataONEorg/dataone_examples', 'size': '3989'}