// This example shows different ways of constructing OPC UA node IDs.
using System;
using OpcLabs.BaseLib;
using OpcLabs.EasyOpc.UA;
using OpcLabs.EasyOpc.UA.AddressSpace;
using OpcLabs.EasyOpc.UA.AddressSpace.Parsing;
using OpcLabs.EasyOpc.UA.AddressSpace.Parsing.Extensions;
using OpcLabs.EasyOpc.UA.AddressSpace.Standard;
using OpcLabs.EasyOpc.UA.OperationModel;
namespace UADocExamples._UANodeId
{
    class _Construction
    {
        // A node ID specifies a namespace (either by an URI or by an index), and an identifier.
        // The identifier can be numeric (an integer), string, GUID, or opaque.
        public static void Main1()
        {
            // A node ID can be specified in string form (so-called expanded text). 
            // The code below specifies a namespace URI (nsu=...), and an integer identifier (i=...).
            UANodeId nodeId1 = new UANodeId("nsu=http://test.org/UA/Data/ ;i=10853");
            Console.WriteLine(nodeId1);
            // Similarly, with a string identifier (s=...).
            UANodeId nodeId2 = new UANodeId("nsu=http://test.org/UA/Data/ ;s=someIdentifier");
            Console.WriteLine(nodeId2);
            // Actually, "s=" can be omitted (not recommended, though).
            UANodeId nodeId3 = new UANodeId("nsu=http://test.org/UA/Data/ ;someIdentifier");
            Console.WriteLine(nodeId3);
            // Notice that the output is normalized - the "s=" is added again.
            // Similarly, with a GUID identifier (g=...).
            UANodeId nodeId4 = new UANodeId("nsu=http://test.org/UA/Data/ ;g=BAEAF004-1E43-4A06-9EF0-E52010D5CD10");
            Console.WriteLine(nodeId4);
            // Notice that the output is normalized - uppercase letters in the GUI are converted to lowercase, etc.
            // Similarly, with an opaque identifier (b=..., in Base64 encoding).
            UANodeId nodeId5 = new UANodeId("nsu=http://test.org/UA/Data/ ;b=AP8=");
            Console.WriteLine(nodeId5);
            // Namespace index can be used instead of namespace URI. The server is allowed to change the namespace 
            // indices between sessions (except for namespace 0), and for this reason, you should avoid the use of
            // namespace indices, and rather use the namespace URIs whenever possible.
            UANodeId nodeId6 = new UANodeId("ns=2;i=10853");
            Console.WriteLine(nodeId6);
            // Namespace index can be also specified together with namespace URI. This is still safe, but may be 
            // a bit quicker to perform, because the client can just verify the namespace URI instead of looking 
            // it up.
            UANodeId nodeId7 = new UANodeId("nsu=http://test.org/UA/Data/ ;ns=2;i=10853");
            Console.WriteLine(nodeId7);
            // When neither namespace URI nor namespace index are given, the node ID is assumed to be in namespace
            // with index 0 and URI "http://opcfoundation.org/UA/", which is reserved by OPC UA standard. There are 
            // many standard nodes that live in this reserved namespace, but no nodes specific to your servers will 
            // be in the reserved namespace, and hence the need to specify the namespace with server-specific nodes.
            UANodeId nodeId8 = new UANodeId("i=2254");
            Console.WriteLine(nodeId8);
            // If you attempt to pass in a string that does not conform to the syntax rules, 
            // a UANodeIdFormatException is thrown.
            try
            {
                UANodeId nodeId9 = new UANodeId("nsu=http://test.org/UA/Data/ ;i=notAnInteger");
                Console.WriteLine(nodeId9);
            }
            catch (UANodeIdFormatException nodeIdFormatException)
            {
                Console.WriteLine($"*** Failure {nodeIdFormatException.Message}");
            }
            // There is a parser object that can be used to parse the expanded texts of node IDs. 
            UANodeIdParser nodeIdParser10 = new UANodeIdParser();
            UANodeId nodeId10 = nodeIdParser10.Parse("nsu=http://test.org/UA/Data/ ;i=10853");
            Console.WriteLine(nodeId10);
            // The parser can be used if you want to parse the expanded text of the node ID but do not want 
            // exceptions be thrown.
            UANodeIdParser nodeIdParser11 = new UANodeIdParser();
            IStringParsingError stringParsingError =
                nodeIdParser11.TryParse("nsu=http://test.org/UA/Data/ ;i=notAnInteger", out UANodeId nodeId11);
            if (stringParsingError is null)
                Console.WriteLine(nodeId11);
            else
                Console.WriteLine($"*** Failure: {stringParsingError.Message}");
            // You can also use the parser if you have node IDs where you want the default namespace be different 
            // from the standard "http://opcfoundation.org/UA/".
            UANodeIdParser nodeIdParser12 = new UANodeIdParser("http://test.org/UA/Data/");
            UANodeId nodeId12 = nodeIdParser12.Parse("i=10853");
            Console.WriteLine(nodeId12);
            // The namespace URI string (or the namespace index, or both) and the identifier can be passed to the
            // constructor separately.
            UANodeId nodeId13 = new UANodeId("http://test.org/UA/Data/", 10853);
            Console.WriteLine(nodeId13);
            // You can create a "null" node ID. Such node ID does not actually identify any valid node in OPC UA, but 
            // is useful as a placeholder or as a starting point for further modifications of its properties.
            UANodeId nodeId14 = new UANodeId();
            Console.WriteLine(nodeId14);
            // Properties of a node ID can be modified individually. The advantage of this approach is that you do 
            // not have to care about syntax of the node ID expanded text.
            UANodeId nodeId15 = new UANodeId();
            nodeId15.NamespaceUriString = "http://test.org/UA/Data/";
            nodeId15.Identifier = 10853;
            Console.WriteLine(nodeId15);
            // The same as above, but using an object initializer list.
            UANodeId nodeId16 = new UANodeId
            {
                NamespaceUriString = "http://test.org/UA/Data/",
                Identifier = 10853
            };
            Console.WriteLine(nodeId16);
            // If you know the type of the identifier upfront, it is safer to use typed properties that correspond 
            // to specific types of identifier. Here, with an integer identifier.
            UANodeId nodeId17 = new UANodeId();
            nodeId17.NamespaceUriString = "http://test.org/UA/Data/";
            nodeId17.NumericIdentifier = 10853;
            Console.WriteLine(nodeId17);
            // Similarly, with a string identifier.
            UANodeId nodeId18 = new UANodeId();
            nodeId18.NamespaceUriString = "http://test.org/UA/Data/";
            nodeId18.StringIdentifier = "someIdentifier";
            Console.WriteLine(nodeId18);
            // Similarly, with a GUID identifier.
            UANodeId nodeId19 = new UANodeId();
            nodeId19.NamespaceUriString = "http://test.org/UA/Data/";
            nodeId19.GuidIdentifier = Guid.Parse("BAEAF004-1E43-4A06-9EF0-E52010D5CD10");
            Console.WriteLine(nodeId19);
            // If you have GUID in its string form, the node ID object can parse it for you.
            UANodeId nodeId20 = new UANodeId();
            nodeId20.NamespaceUriString = "http://test.org/UA/Data/";
            nodeId20.GuidIdentifierString = "BAEAF004-1E43-4A06-9EF0-E52010D5CD10";
            Console.WriteLine(nodeId20);
            // And, with an opaque identifier.
            UANodeId nodeId21 = new UANodeId();
            nodeId21.NamespaceUriString = "http://test.org/UA/Data/";
            nodeId21.OpaqueIdentifier = new byte[] {0x00, 0xFF};
            Console.WriteLine(nodeId21);
            // Assigning an expanded text to a node ID parses the value being assigned and sets all corresponding
            // properties accordingly.
            UANodeId nodeId22 = new UANodeId();
            nodeId22.ExpandedText = "nsu=http://test.org/UA/Data/ ;i=10853";
            Console.WriteLine(nodeId22);
            // There is an implicit conversion from a string (representing the expanded text) to a node ID.
            // You can therefore use the expanded text (string) in place of any node ID object directly.
            UANodeId nodeId23 = "nsu=http://test.org/UA/Data/ ;i=10853";
            Console.WriteLine(nodeId23);
            // There is a copy constructor as well, creating a clone of an existing node ID.
            UANodeId nodeId24a = new UANodeId("nsu=http://test.org/UA/Data/ ;i=10853");
            Console.WriteLine(nodeId24a);
            UANodeId nodeId24b = new UANodeId(nodeId24a);
            Console.WriteLine(nodeId24b);
            // We have provided static classes with properties that correspond to all standard nodes specified by 
            // OPC UA. You can simply refer to these node IDs in your code.
            // The class names are UADataTypeIds, UAMethodIds, UAObjectIds, UAObjectTypeIds, UAReferenceTypeIds, 
            // UAVariableIds and UAVariableTypeIds.
            UANodeId nodeId25 = UAObjectIds.TypesFolder;
            Console.WriteLine(nodeId25);
            // When the UANodeId equals to one of the standard nodes, it is output in the shortened form - as the standard
            // name only.
            // You can also refer to any standard node using its name (in a string form).
            // Note that assigning a non-existing standard name is not allowed, and throws ArgumentException.
            UANodeId nodeId26 = new UANodeId();
            nodeId26.StandardName = "TypesFolder";
            Console.WriteLine(nodeId26);
            // When you browse for nodes in the OPC UA server, every returned node element contains a node ID that
            // you can use further.
            var client27 = new EasyUAClient();
            try
            {
                UANodeElementCollection nodeElementCollection27 = client27.Browse(
                        "opc.tcp://opcua.demo-this.com:51210/UA/SampleServer",
                        UAObjectIds.Server,
                        new UABrowseParameters(UANodeClass.All, new[] { UAReferenceTypeIds.References }));
                if (nodeElementCollection27.Count != 0)
                {
                    UANodeId nodeId27 = nodeElementCollection27[0].NodeId;
                    Console.WriteLine(nodeId27);
                }
            }
            catch (UAException uaException)
            {
                Console.WriteLine("Failure: {0}", uaException.GetBaseException().Message);
            }
            // As above, but using a constructor that takes a node element as an input.
            var client28 = new EasyUAClient();
            try
            {
                UANodeElementCollection nodeElementCollection28 = client28.Browse(
                    "opc.tcp://opcua.demo-this.com:51210/UA/SampleServer",
                    UAObjectIds.Server,
                    new UABrowseParameters(UANodeClass.All, new[] { UAReferenceTypeIds.References }));
                if (nodeElementCollection28.Count != 0)
                {
                    UANodeId nodeId28 = new UANodeId(nodeElementCollection28[0]);
                    Console.WriteLine(nodeId28);
                }
            }
            catch (UAException uaException)
            {
                Console.WriteLine("Failure: {0}", uaException.GetBaseException().Message);
            }
            // Or, there is an explicit conversion from a node descriptor as well.
            var client29 = new EasyUAClient();
            try
            {
                UANodeElementCollection nodeElementCollection29 = client29.Browse(
                    "opc.tcp://opcua.demo-this.com:51210/UA/SampleServer",
                    UAObjectIds.Server,
                    new UABrowseParameters(UANodeClass.All, new[] { UAReferenceTypeIds.References }));
                if (nodeElementCollection29.Count != 0)
                {
                    UANodeId nodeId29 = (UANodeId) nodeElementCollection29[0];
                    Console.WriteLine(nodeId29);
                }
            }
            catch (UAException uaException)
            {
                Console.WriteLine("Failure: {0}", uaException.GetBaseException().Message);
            }
        }
    }
}
	 
	
		# This example shows different ways of constructing OPC UA node IDs.
# The QuickOPC package is needed. Install it using "pip install opclabs_quickopc".
import opclabs_quickopc
# Import .NET namespaces.
from System import *
from OpcLabs.EasyOpc.UA import *
from OpcLabs.EasyOpc.UA.AddressSpace import *
from OpcLabs.EasyOpc.UA.AddressSpace.Parsing import *
from OpcLabs.EasyOpc.UA.AddressSpace.Parsing.Extensions import *
from OpcLabs.EasyOpc.UA.AddressSpace.Standard import *
# A node ID specifies a namespace (either by an URI or by an index), and an identifier.
# The identifier can be numeric (an integer), string, GUID, or opaque.
#
# A node ID can be specified in string form (so-called expanded text).
# The code below specifies a namespace URI (nsu=...), and an integer identifier (i=...).
nodeId1 = UANodeId('nsu=http://test.org/UA/Data/ ;i=10853')
print(nodeId1)
# Similarly, with a string identifier (s=...).
nodeId2 = UANodeId('nsu=http://test.org/UA/Data/ ;s=someIdentifier')
print(nodeId2)
# Actually, "s=" can be omitted (not recommended, though).
nodeId3 = UANodeId('nsu=http://test.org/UA/Data/ ;someIdentifier')
print(nodeId3)
# Similarly, with a GUID identifier (g=...).
nodeId4 = UANodeId('nsu=http://test.org/UA/Data/ ;g=BAEAF004-1E43-4A06-9EF0-E52010D5CD10')
print(nodeId4)
# Similarly, with an opaque identifier (b=..., in Base64 encoding).
nodeId5 = UANodeId('nsu=http://test.org/UA/Data/ ;b=AP8=')
print(nodeId5)
# Namespace index can be used instead of namespace URI. The server is allowed to change the namespace
# indices between sessions (except for namespace 0), and for this reason, you should avoid the use of
# namespace indices, and rather use the namespace URIs whenever possible.
nodeId6 = UANodeId('ns=2;i=10853')
print(nodeId6)
# Namespace index can be also specified together with namespace URI. This is still safe, but may be
# a bit quicker to perform, because the client can just verify the namespace URI instead of looking
# it up.
nodeId7 = UANodeId('nsu=http://test.org/UA/Data/ ;ns=2;i=10853')
print(nodeId7)
# When neither namespace URI nor namespace index are given, the node ID is assumed to be in namespace
# with index 0 and URI "http://opcfoundation.org/UA/", which is reserved by OPC UA standard. There are
# many standard nodes that live in this reserved namespace, but no nodes specific to your servers will
# be in the reserved namespace, and hence the need to specify the namespace with server-specific nodes.
nodeId8 = UANodeId('i=2254')
print(nodeId8)
# If you attempt to pass in a string that does not conform to the syntax rules,
# a UANodeIdFormatException is thrown.
try:
    nodeId9 = UANodeId('nsu=http://test.org/UA/Data/ ;i=notAnInteger')
except UANodeIdFormatException as nodeIdFormatException:
    print('*** Failure: ', nodeIdFormatException.Message, sep='')
# There is a parser object that can be used to parse the expanded texts of node IDs.
nodeIdParser10 = UANodeIdParser()
nodeId10 = IUANodeIdParserExtension.Parse(nodeIdParser10, 'nsu=http://test.org/UA/Data/ ;i=10853')
print(nodeId10)
# The parser can be used if you want to parse the expanded text of the node ID but do not want
# exceptions be thrown.
nodeIdParser11 = UANodeIdParser()
stringParsingError, nodeId11 = IUANodeIdParserExtension.TryParse(nodeIdParser11,
                                                                 'nsu=http://test.org/UA/Data/ ;i=notAnInteger',
                                                                 UANodeId())    # placeholder for 'out'
if stringParsingError is None:
    print(nodeId11)
else:
    print('*** Failure: ', stringParsingError.Message, sep='')
# You can also use the parser if you have node IDs where you want the default namespace be different
# from the standard "http://opcfoundation.org/UA/".
nodeIdParser12 = UANodeIdParser('http://test.org/UA/Data/')
nodeId12 = IUANodeIdParserExtension.Parse(nodeIdParser12, 'i=10853')
print(nodeId12)
# The namespace URI string (or the namespace index, or both) and the identifier can be passed to the
# constructor separately.
nodeId13 = UANodeId('http://test.org/UA/Data/', 10853)
print(nodeId13)
# You can create a "null" node ID. Such node ID does not actually identify any valid node in OPC UA, but
# is useful as a placeholder or as a starting point for further modifications of its properties.
nodeId14 = UANodeId()
print(nodeId14)
# Properties of a node ID can be modified individually. The advantage of this approach is that you do
# not have to care about syntax of the node ID expanded text.
nodeId15 = UANodeId()
nodeId15.NamespaceUriString = 'http://test.org/UA/Data/'
nodeId15.Identifier = 10853
print(nodeId15)
# If you know the type of the identifier upfront, it is safer to use typed properties that correspond
# to specific types of identifier. Here, with an integer identifier.
nodeId17 = UANodeId()
nodeId17.NamespaceUriString = 'http://test.org/UA/Data/'
nodeId17.NumericIdentifier = 10853
print(nodeId17)
# Similarly, with a string identifier.
nodeId18 = UANodeId()
nodeId18.NamespaceUriString = 'http://test.org/UA/Data/'
nodeId18.StringIdentifier = 'someIdentifier'
print(nodeId18)
# Similarly, with a GUID identifier.
nodeId19 = UANodeId()
nodeId19.NamespaceUriString = 'http://test.org/UA/Data/'
nodeId19.GuidIdentifier = Guid.Parse('BAEAF004-1E43-4A06-9EF0-E52010D5CD10')
print(nodeId19)
# If you have GUID in its string form, the node ID object can parse it for you.
nodeId20 = UANodeId()
nodeId20.NamespaceUriString = 'http://test.org/UA/Data/'
nodeId20.GuidIdentifierString = 'BAEAF004-1E43-4A06-9EF0-E52010D5CD10'
print(nodeId20)
# And, with an opaque identifier.
nodeId21 = UANodeId()
nodeId21.NamespaceUriString = 'http://test.org/UA/Data/'
nodeId21.OpaqueIdentifier = [0x00, 0xFF]
print(nodeId21)
# Assigning an expanded text to a node ID parses the value being assigned and sets all corresponding
# properties accordingly.
nodeId22 = UANodeId()
nodeId22.ExpandedText = 'nsu=http://test.org/UA/Data/ ;i=10853'
print(nodeId22)
# There is a copy constructor as well, creating a clone of an existing node ID.
nodeId24a = UANodeId('nsu=http://test.org/UA/Data/ ;i=10853')
print(nodeId24a)
nodeId24b = UANodeId(nodeId24a)
print(nodeId24b)
# We have provided static classes with properties that correspond to all standard nodes specified by
# OPC UA. You can simply refer to these node IDs in your code.
# The class names are UADataTypeIds, UAMethodIds, UAObjectIds, UAObjectTypeIds, UAReferenceTypeIds,
# UAVariableIds and UAVariableTypeIds.
nodeId25 = UAObjectIds.TypesFolder
print(nodeId25)
# When the UANodeId equals to one of the standard nodes, it is output in the shortened form - as the standard
# name only.
# You can also refer to any standard node using its name (in a string form).
# Note that assigning a non-existing standard name is not allowed, and throws ArgumentException.
nodeId26 = UANodeId()
nodeId26.StandardName = "TypesFolder"
print(nodeId26)
# When you browse for nodes in the OPC UA server, every returned node element contains a node ID that
# you can use further.
client27 = EasyUAClient()
try:
    nodeElementCollection27 = IEasyUAClientExtension.Browse(client27,
        UAEndpointDescriptor('opc.tcp://opcua.demo-this.com:51210/UA/SampleServer'),
        UANodeDescriptor(UAObjectIds.Server),
        UABrowseParameters(UANodeClass.All, UAReferenceTypeIds.References))
    if nodeElementCollection27.Count != 0:
        nodeId27 = nodeElementCollection27.get_Item(0).NodeId
        print(nodeId27)
except UAException as uaException:
    print('*** Failure: ', uaException.GetBaseException().Message, sep='')
# As above, but using a constructor that takes a node element as an input.
client28 = EasyUAClient()
try:
    nodeElementCollection28 = IEasyUAClientExtension.Browse(client28,
        UAEndpointDescriptor('opc.tcp://opcua.demo-this.com:51210/UA/SampleServer'),
        UANodeDescriptor(UAObjectIds.Server),
        UABrowseParameters(UANodeClass.All, UAReferenceTypeIds.References))
    if nodeElementCollection28.Count != 0:
        nodeId28 = UANodeId(nodeElementCollection28.get_Item(0))
        print(nodeId28)
except UAException as uaException:
    print('*** Failure: ', uaException.GetBaseException().Message, sep='')
# Or, there is an explicit conversion from a node descriptor as well.
client29 = EasyUAClient()
try:
    nodeElementCollection29 = IEasyUAClientExtension.Browse(client29,
        UAEndpointDescriptor('opc.tcp://opcua.demo-this.com:51210/UA/SampleServer'),
        UANodeDescriptor(UAObjectIds.Server),
        UABrowseParameters(UANodeClass.All, UAReferenceTypeIds.References))
    if nodeElementCollection29.Count != 0:
        # FromUANodeDescriptor can be used instead of op_Explicit, too.
        nodeId29 = UANodeId.op_Explicit(UANodeDescriptor(nodeElementCollection29.get_Item(0)))
        print(nodeId29)
except UAException as uaException:
    print('*** Failure: ', uaException.GetBaseException().Message, sep='')
print()
print('Finished.')
	 
	
		' This example shows different ways of constructing OPC UA node IDs.
Imports System
Imports OpcLabs.BaseLib
Imports OpcLabs.EasyOpc.UA
Imports OpcLabs.EasyOpc.UA.AddressSpace
Imports OpcLabs.EasyOpc.UA.AddressSpace.Parsing
Imports OpcLabs.EasyOpc.UA.AddressSpace.Parsing.Extensions
Imports OpcLabs.EasyOpc.UA.AddressSpace.Standard
Namespace _UANodeId
    Friend Class _Construction
        Public Shared Sub Main1()
            ' A node ID can be specified in string form (so-called expanded text). 
            ' The code below specifies a namespace URI (nsu=...), and an integer identifier (i=...).
            Dim nodeId1 = New UANodeId("nsu=http://test.org/UA/Data/ ;i=10853")
            Console.WriteLine(nodeId1)
            ' Similarly, with a string identifier (s=...).
            Dim nodeId2 = New UANodeId("nsu=http://test.org/UA/Data/ ;s=someIdentifier")
            Console.WriteLine(nodeId2)
            ' Actually, "s=" can be omitted (not recommended, though)
            Dim nodeId3 = New UANodeId("nsu=http://test.org/UA/Data/ ;someIdentifier")
            Console.WriteLine(nodeId3)
            ' Similarly, with a GUID identifier (g=...)
            Dim nodeId4 = New UANodeId("nsu=http://test.org/UA/Data/ ;g=BAEAF004-1E43-4A06-9EF0-E52010D5CD10")
            Console.WriteLine(nodeId4)
            ' Similarly, with an opaque identifier (b=..., in Base64 encoding).
            Dim nodeId5 = New UANodeId("nsu=http://test.org/UA/Data/ ;b=AP8=")
            Console.WriteLine(nodeId5)
            ' Namespace index can be used instead of namespace URI. The server is allowed to change the namespace 
            ' indices between sessions, and for this reason, you should avoid the use of namespace indices, and
            ' rather use the namespace URIs whenever possible.
            Dim nodeId6 = New UANodeId("ns=2;i=10853")
            Console.WriteLine(nodeId6)
            ' Namespace index can be also specified together with namespace URI. This is still safe, but may be 
            ' a bit quicker to perform, because the client can just verify the namespace URI instead of looking 
            ' it up.
            Dim nodeId7 = New UANodeId("nsu=http://test.org/UA/Data/ ;ns=2;i=10853")
            Console.WriteLine(nodeId7)
            ' When neither namespace URI nor namespace index are given, the node ID is assumed to be in namespace
            ' with index 0 and URI "http://opcfoundation.org/UA/", which is reserved by OPC UA standard. There are 
            ' many standard nodes that live in this reserved namespace, but no nodes specific to your servers will 
            ' be in the reserved namespace, and hence the need to specify the namespace with server-specific nodes.
            Dim nodeId8 = New UANodeId("i=2254")
            Console.WriteLine(nodeId8)
            ' If you attempt to pass in a string that does not conform to the syntax rules, 
            ' a UANodeIdFormatException is thrown.
            Try
                Dim nodeId9 = New UANodeId("nsu=http://test.org/UA/Data/ ;i=notAnInteger")
                Console.WriteLine(nodeId9)
            Catch nodeIdFormatException As UANodeIdFormatException
                Console.WriteLine(nodeIdFormatException.Message)
            End Try
            ' There is a parser object that can be used to parse the expanded textx of node IDs. 
            Dim nodeIdParser10 = New UANodeIdParser()
            Dim nodeId10 = nodeIdParser10.Parse("nsu=http://test.org/UA/Data/ ;i=10853")
            Console.WriteLine(nodeId10)
            ' The parser can be used if you want to parse the expanded text of the node ID but do not want 
            ' exceptions be thrown.
            Dim nodeIdParser11 = New UANodeIdParser()
            Dim nodeId11 As UANodeId = Nothing
            Dim stringParsingError As IStringParsingError =
                    nodeIdParser11.TryParse("nsu=http://test.org/UA/Data/ ;i=notAnInteger", nodeId11)
            If stringParsingError Is Nothing Then
                Console.WriteLine(nodeId11)
            Else
                Console.WriteLine(stringParsingError.Message)
            End If
            ' You can also use the parser if you have node IDs where you want the default namespace be different 
            ' from the standard "http://opcfoundation.org/UA/".
            Dim nodeIdParser12 = New UANodeIdParser("http://test.org/UA/Data/")
            Dim nodeId12 = nodeIdParser12.Parse("i=10853")
            Console.WriteLine(nodeId12)
            ' The namespace URI string (or the namespace index, or both) and the identifier can be passed to the
            ' constructor separately.
            Dim nodeId13 = New UANodeId("http://test.org/UA/Data/", 10853)
            Console.WriteLine(nodeId13)
            ' You can create a "null" node ID. Such node ID does not actually identify any valid node in OPC UA, but 
            ' is useful as a placeholder or as a starting point for further modifications of its properties.
            Dim nodeId14 = New UANodeId()
            Console.WriteLine(nodeId14)
            ' Properties of a node ID can be modified individually. The advantage of this approach is that you do 
            ' not have to care about syntax of the node ID expanded text.
            Dim nodeId15 = New UANodeId()
            nodeId15.NamespaceUriString = "http://test.org/UA/Data/"
            nodeId15.Identifier = 10853
            Console.WriteLine(nodeId15)
            ' The same as above, but using an object initializer list.
            Dim nodeId16 = New UANodeId With
            {
                .NamespaceUriString = "http://test.org/UA/Data/",
                .Identifier = 10853
            }
            Console.WriteLine(nodeId16)
            ' If you know the type of the identifier upfront, it is safer to use typed properties that correspond 
            ' to specific types of identifier. Here, with an integer identifier.
            Dim nodeId17 = New UANodeId()
            nodeId17.NamespaceUriString = "http://test.org/UA/Data/"
            nodeId17.NumericIdentifier = 10853
            Console.WriteLine(nodeId17)
            ' Similarly, with a string identifier.
            Dim nodeId18 = New UANodeId()
            nodeId18.NamespaceUriString = "http://test.org/UA/Data/"
            nodeId18.StringIdentifier = "someIdentifier"
            Console.WriteLine(nodeId18)
            ' Similarly, with a GUID identifier.
            Dim nodeId19 = New UANodeId()
            nodeId19.NamespaceUriString = "http://test.org/UA/Data/"
            nodeId19.GuidIdentifier = Guid.Parse("BAEAF004-1E43-4A06-9EF0-E52010D5CD10")
            Console.WriteLine(nodeId19)
            ' If you have GUID in its string form, the node ID object can parse it for you.
            Dim nodeId20 = New UANodeId()
            nodeId20.NamespaceUriString = "http://test.org/UA/Data/"
            nodeId20.GuidIdentifierString = "BAEAF004-1E43-4A06-9EF0-E52010D5CD10"
            Console.WriteLine(nodeId20)
            ' And, with an opaque identifier.
            Dim nodeId21 = New UANodeId()
            nodeId21.NamespaceUriString = "http://test.org/UA/Data/"
            nodeId21.OpaqueIdentifier = {&H0, &HFF}
            Console.WriteLine(nodeId21)
            ' Assigning an expanded text to a node ID parses the value being assigned and sets all corresponding
            ' properties accordingly.
            Dim nodeId22 = New UANodeId()
            nodeId22.ExpandedText = "nsu=http://test.org/UA/Data/ ;i=10853"
            Console.WriteLine(nodeId22)
            ' There is an implicit conversion from a string (representing the expanded text) to a node ID.
            ' You can therefore use the expanded text (string) in place of any node ID object directly.
            Dim nodeId23 = "nsu=http://test.org/UA/Data/ ;i=10853"
            Console.WriteLine(nodeId23)
            ' There is a copy constructor as well, creating a clone of an existing node ID.
            Dim nodeId24a = New UANodeId("nsu=http://test.org/UA/Data/ ;i=10853")
            Console.WriteLine(nodeId24a)
            Dim nodeId24b = New UANodeId(nodeId24a)
            Console.WriteLine(nodeId24b)
            ' We have provided static classes with properties that correspond to all standard nodes specified by 
            ' OPC UA. You can simply refer to these node IDs in your code.
            ' The class names are UADataTypeIds, UAMethodIds, UAObjectIds, UAObjectTypeIds, UAReferenceTypeIds, 
            ' UAVariableIds and UAVariableTypeIds.
            Dim nodeId25 = UAObjectIds.TypesFolder
            Console.WriteLine(nodeId25)
            ' You can also refer to any standard node using its name (in a string form).
            ' Note that assigning a non-existing standard name is not allowed, and throws ArgumentException.
            Dim nodeId26 = New UANodeId()
            nodeId26.StandardName = "TypesFolder"
            Console.WriteLine(nodeId26)
            ' When you browse for nodes in the OPC UA server, every returned node element contains a node ID that
            ' you can use further.
            Dim client27 = New EasyUAClient()
            Dim nodeElementCollection27 = client27.Browse(
                "opc.tcp://opcua.demo-this.com:51210/UA/SampleServer",
                UAObjectIds.Server,
                New UABrowseParameters(UANodeClass.All, {UAReferenceTypeIds.References}))
            Dim nodeId27 = nodeElementCollection27(0).NodeId
            Console.WriteLine(nodeId27)
            ' As above, but using a constructor that takes a node element as an input.
            Dim client28 = New EasyUAClient()
            Dim nodeElementCollection28 = client28.Browse(
                "opc.tcp://opcua.demo-this.com:51210/UA/SampleServer",
                UAObjectIds.Server,
                New UABrowseParameters(UANodeClass.All, {UAReferenceTypeIds.References}))
            Dim nodeId28 = New UANodeId(nodeElementCollection28(0))
            Console.WriteLine(nodeId28)
            ' Or, there is an explicit conversion from a node element as well.
            Dim client29 = New EasyUAClient()
            Dim nodeElementCollection29 = client29.Browse(
                "opc.tcp://opcua.demo-this.com:51210/UA/SampleServer",
                UAObjectIds.Server,
                New UABrowseParameters(UANodeClass.All, {UAReferenceTypeIds.References}))
            Dim nodeId29 = CType(nodeElementCollection29(0), UANodeId)
            Console.WriteLine(nodeId29)
        End Sub
    End Class
End Namespace