Skip to content

Commit 35db94c

Browse files
Copilotromanett
andauthored
Add client-based NodeSet2 export functionality (#3400)
* Initial plan * Add client-based nodeset export functionality Co-authored-by: romanett <[email protected]> * Add tests for client-based nodeset export functionality Co-authored-by: romanett <[email protected]> * Add documentation for client-based nodeset export feature Co-authored-by: romanett <[email protected]> --------- Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: romanett <[email protected]>
1 parent 5371f88 commit 35db94c

File tree

5 files changed

+851
-0
lines changed

5 files changed

+851
-0
lines changed

Applications/ConsoleReferenceClient/ClientSamples.cs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1596,6 +1596,37 @@ private static BrowseDescriptionCollection CreateBrowseDescriptionCollectionFrom
15961596
return browseDescriptionCollection;
15971597
}
15981598

1599+
/// <summary>
1600+
/// Exports nodes to a NodeSet2 XML file.
1601+
/// </summary>
1602+
/// <param name="session">The session to use for exporting.</param>
1603+
/// <param name="nodes">The list of nodes to export.</param>
1604+
/// <param name="filePath">The path where the NodeSet2 XML file will be saved.</param>
1605+
public void ExportNodesToNodeSet2(ISession session, IList<INode> nodes, string filePath)
1606+
{
1607+
m_logger.LogInformation("Exporting {Count} nodes to {FilePath}...", nodes.Count, filePath);
1608+
1609+
var stopwatch = new Stopwatch();
1610+
stopwatch.Start();
1611+
1612+
using var outputStream = new FileStream(filePath, FileMode.Create);
1613+
var systemContext = new SystemContext(m_telemetry)
1614+
{
1615+
NamespaceUris = session.NamespaceUris,
1616+
ServerUris = session.ServerUris
1617+
};
1618+
1619+
CoreClientUtils.ExportNodesToNodeSet2(systemContext, nodes, outputStream);
1620+
1621+
stopwatch.Stop();
1622+
1623+
m_logger.LogInformation(
1624+
"Exported {Count} nodes to {FilePath} in {Duration}ms",
1625+
nodes.Count,
1626+
filePath,
1627+
stopwatch.ElapsedMilliseconds);
1628+
}
1629+
15991630
/// <summary>
16001631
/// Create the continuation point collection from the browse result
16011632
/// collection for the BrowseNext service.

Docs/NodeSetExport.md

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
# Client-based NodeSet Export
2+
3+
The OPC UA .NET Standard stack provides the ability to export the address space from an OPC UA server to a NodeSet2 XML file using the client library. This allows you to browse a server's address space and save it to a file that can be used for documentation, analysis, or import into other systems.
4+
5+
## Overview
6+
7+
The client-based NodeSet export feature enables:
8+
9+
- Browsing and collecting nodes from an OPC UA server
10+
- Converting client-side node representations (`INode`) to server-side representations (`NodeState`)
11+
- Exporting nodes to standard NodeSet2 XML format
12+
- Round-tripping: exported NodeSets can be imported using existing import functionality
13+
14+
## Usage
15+
16+
### Basic Example
17+
18+
```csharp
19+
using System.IO;
20+
using Opc.Ua;
21+
using Opc.Ua.Client;
22+
23+
// Connect to server and create session
24+
var session = await Session.CreateAsync(/*...*/);
25+
26+
// Browse to collect nodes
27+
var browser = new Browser(session)
28+
{
29+
BrowseDirection = BrowseDirection.Forward,
30+
ReferenceTypeId = ReferenceTypeIds.HierarchicalReferences,
31+
IncludeSubtypes = true,
32+
NodeClassMask = 0
33+
};
34+
35+
var nodesToBrowse = new NodeIdCollection { ObjectIds.Server };
36+
var allNodes = new List<INode>();
37+
38+
// Browse and collect nodes
39+
ReferenceDescriptionCollection references = await browser.BrowseAsync(nodesToBrowse[0]);
40+
41+
foreach (ReferenceDescription reference in references)
42+
{
43+
INode node = await session.NodeCache.FindAsync(reference.NodeId);
44+
if (node != null)
45+
{
46+
allNodes.Add(node);
47+
}
48+
}
49+
50+
// Export to NodeSet2 file
51+
using (var stream = new FileStream("exported-nodeset.xml", FileMode.Create))
52+
{
53+
var systemContext = new SystemContext(telemetry)
54+
{
55+
NamespaceUris = session.NamespaceUris,
56+
ServerUris = session.ServerUris
57+
};
58+
59+
CoreClientUtils.ExportNodesToNodeSet2(systemContext, allNodes, stream);
60+
}
61+
```
62+
63+
### Using the Console Reference Client
64+
65+
The console reference client (`ClientSamples` class) includes a helper method for exporting nodes:
66+
67+
```csharp
68+
// Browse and collect nodes using the existing helper
69+
IList<INode> nodes = await clientSamples.FetchAllNodesNodeCacheAsync(
70+
uaClient,
71+
ObjectIds.ObjectsFolder, // Starting node
72+
fetchTree: true, // Recursively browse the tree
73+
addRootNode: true, // Include the root node
74+
filterUATypes: true, // Filter out namespace 0 nodes
75+
clearNodeCache: true
76+
);
77+
78+
// Export to NodeSet2 file
79+
clientSamples.ExportNodesToNodeSet2(session, nodes, "address-space.xml");
80+
```
81+
82+
## Supported Node Types
83+
84+
The export functionality supports all standard OPC UA node types:
85+
86+
- **Object nodes** - Objects and their properties
87+
- **Variable nodes** - Variables with their values and data types
88+
- **Method nodes** - Methods with their executable status
89+
- **ObjectType nodes** - Object type definitions
90+
- **VariableType nodes** - Variable type definitions
91+
- **DataType nodes** - Data type definitions
92+
- **ReferenceType nodes** - Reference type definitions
93+
- **View nodes** - View definitions
94+
95+
## Features
96+
97+
### Node Attributes Exported
98+
99+
For each node, the following attributes are exported (where applicable):
100+
101+
- NodeId
102+
- BrowseName
103+
- DisplayName
104+
- Description
105+
- WriteMask and UserWriteMask
106+
- References to other nodes
107+
- Type-specific attributes (e.g., DataType for variables, EventNotifier for objects)
108+
109+
### Namespace Handling
110+
111+
The export functionality properly handles:
112+
113+
- Multiple namespaces
114+
- Namespace URIs are included in the exported NodeSet
115+
- NodeIds are correctly mapped to namespace indices
116+
117+
### References
118+
119+
All references between nodes are preserved in the export, including:
120+
121+
- Hierarchical references (e.g., HasComponent, HasProperty)
122+
- Type definition references (e.g., HasTypeDefinition)
123+
- Organizing references
124+
- Custom reference types
125+
126+
## Limitations
127+
128+
- The export creates a snapshot of the address space at the time of browsing
129+
- Dynamic values are captured as they exist at export time
130+
- Not all server-specific internal state may be preserved
131+
- Complex type definitions require the complex types system to be loaded
132+
133+
## API Reference
134+
135+
### CoreClientUtils.ExportNodesToNodeSet2
136+
137+
```csharp
138+
public static void ExportNodesToNodeSet2(
139+
ISystemContext context,
140+
IList<INode> nodes,
141+
Stream outputStream)
142+
```
143+
144+
**Parameters:**
145+
- `context` - System context containing namespace and server URI information
146+
- `nodes` - List of nodes to export
147+
- `outputStream` - Stream to write the NodeSet2 XML to
148+
149+
**Exceptions:**
150+
- `ArgumentNullException` - If any parameter is null
151+
152+
### ClientSamples.ExportNodesToNodeSet2
153+
154+
```csharp
155+
public void ExportNodesToNodeSet2(
156+
ISession session,
157+
IList<INode> nodes,
158+
string filePath)
159+
```
160+
161+
**Parameters:**
162+
- `session` - Active session to use for namespace information
163+
- `nodes` - List of nodes to export
164+
- `filePath` - Path where the NodeSet2 XML file will be saved
165+
166+
## Related Topics
167+
168+
- [Working with ComplexTypes](ComplexTypes.md)
169+
- [Console Reference Client](../Applications/ConsoleReferenceClient/README.md)
170+
- OPC UA NodeSet2 XML Schema specification
171+
172+
## Examples
173+
174+
For complete examples of using the NodeSet export functionality, see:
175+
176+
- `Tests/Opc.Ua.Client.Tests/NodeSetExportTest.cs` - Unit tests demonstrating various export scenarios
177+
- `Applications/ConsoleReferenceClient/ClientSamples.cs` - Integration in the reference client
178+
179+
## See Also
180+
181+
- [OPC UA Specification Part 6 - Mappings](https://reference.opcfoundation.org/Core/Part6/v105/)
182+
- NodeSet2 XML Schema: `Stack/Opc.Ua.Core/Schema/UANodeSet.xsd`

Docs/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ Here is a list of available documentation for different topics:
1212
* Support for [WellKnownRoles & RoleBasedUserManagement](RoleBasedUserManagement.md).
1313
* Support for [ECC Certificates](EccProfiles.md).
1414
* Working with [ComplexTypes](ComplexTypes.md) - Custom structures and enumerations.
15+
* Client-based [NodeSet Export](NodeSetExport.md) - Export server address space to NodeSet2 XML.
1516

1617
## Reference application related
1718

0 commit comments

Comments
 (0)