Commit 441f33e2 authored by oroulet's avatar oroulet

bugfix xml 2

parent ab146464
......@@ -352,6 +352,7 @@ async def create_encoding(parent, nodeid, bname):
or namespace index, name
"""
nodeid, qname = _parse_nodeid_qname(nodeid, bname)
qname.NamespaceIndex = 0 # encoding bname idx must be 0
return make_node(parent.server, await _create_encoding(parent.server, parent.nodeid, nodeid, qname))
......
......@@ -30,7 +30,7 @@ def new_struct_field(name, dtype, array=False, optional=False, description=""):
elif isinstance(dtype, Node):
field.DataType = dtype.nodeid
else:
raise ValueError(f"Datatype of a field must be a NodeId, not {dtype} of type {type(dtype)}")
raise ValueError(f"DataType of a field must be a NodeId, not {dtype} of type {type(dtype)}")
if array:
field.ValueRank = ua.ValueRank.OneOrMoreDimensions
field.ArrayDimensions = [1]
......@@ -56,7 +56,7 @@ async def new_struct(server, idx, name, fields):
sdef.StructureType = ua.StructureType.StructureWithOptionalFields
break
sdef.Fields = fields
sdef.BaseDatatype = server.nodes.base_data_type.nodeid
sdef.BaseDataType = server.nodes.base_data_type.nodeid
sdef.DefaultEncodingId = enc.nodeid
await dtype.write_data_type_definition(sdef)
......@@ -65,7 +65,6 @@ async def new_struct(server, idx, name, fields):
async def new_enum(server, idx, name, values):
edef = ua.EnumDefinition()
edef.Name = name
counter = 0
for val_name in values:
field = ua.EnumField()
......@@ -272,7 +271,7 @@ async def load_data_type_definitions(server, base_node=None):
async def _read_data_type_definition(server, desc):
if desc.BrowseName.Name == "FilterOperand":
#FIXME: find out why that one is not in ua namespace...
# FIXME: find out why that one is not in ua namespace...
return None
# FIXME: this is fishy, we may have same name in different Namespaces
if hasattr(ua, desc.BrowseName.Name):
......
......@@ -44,30 +44,28 @@ class XmlExporter:
self.etree = Et.ElementTree(Et.Element('UANodeSet', node_write_attributes))
async def build_etree(self, node_list, uris=None):
async def build_etree(self, node_list):
"""
Create an XML etree object from a list of nodes; custom namespace uris are optional
Create an XML etree object from a list of nodes;
Namespaces used by nodes are always exported for consistency.
Args:
node_list: list of Node objects for export
uris: list of namespace uri strings
Returns:
"""
self.logger.info('Building XML etree')
await self._add_namespaces(node_list, uris)
await self._add_namespaces(node_list)
# add all nodes in the list to the XML etree
for node in node_list:
await self.node_to_etree(node)
# add aliases to the XML etree
self._add_alias_els()
async def _add_namespaces(self, nodes, uris):
idxs = await self._get_ns_idxs_of_nodes(nodes)
async def _add_namespaces(self, nodes):
ns_array = await self.server.get_namespace_array()
# now add index of provided uris if necessary
if uris:
self._add_idxs_from_uris(idxs, uris, ns_array)
idxs = await self._get_ns_idxs_of_nodes(nodes)
# now create a dict of idx_in_address_space to idx_in_exported_file
self._addr_idx_to_xml_idx = self._make_idx_dict(idxs, ns_array)
ns_to_export = [ns_array[i] for i in sorted(list(self._addr_idx_to_xml_idx.keys())) if i != 0]
......@@ -308,14 +306,14 @@ class XmlExporter:
elif isinstance(sdef, ua.EnumDefinition):
self._enum_fields_to_etree(bname, sdef_el, sdef)
else:
self.logger.warning("Unknown DatatypeSpecification elemnt: %s", sdef)
self.logger.warning("Unknown DataTypeSpecification elemnt: %s", sdef)
await self._add_ref_els(obj_el, obj)
def _structure_fields_to_etree(self, bname, sdef_el, sdef):
for field in sdef.Fields:
field_el = Et.SubElement(sdef_el, 'Field')
field_el.attrib['Name'] = field.Name
field_el.attrib['Datatype'] = field.DataType.to_string()
field_el.attrib['DataType'] = field.DataType.to_string()
if field.ValueRank != -1:
field_el.attrib['ValueRank'] = str(int(field.ValueRank))
if field.ArrayDimensions:
......
......@@ -494,8 +494,6 @@ class XmlImporter:
if not obj.definitions:
return None
edef = ua.EnumDefinition()
if obj.parent:
edef.BaseDataType = obj.parent
for field in obj.definitions:
f = ua.EnumField()
f.Name = field.name
......@@ -521,7 +519,6 @@ class XmlImporter:
break
optional = False
for field in obj.definitions:
print("IMPORT FIEL", field.name, field.datatype)
f = ua.StructureField()
f.Name = field.name
f.DataType = field.datatype
......
......@@ -69,7 +69,7 @@ class NodeData:
class Field:
def __init__(self, data):
self.datatype = data.get("Datatype", "")
self.datatype = data.get("DataType", "")
self.name = data.get("Name")
self.dname = data.get("DisplayName", "")
self.optional = bool(data.get("IsOptional", False))
......
......@@ -546,15 +546,8 @@ class Server:
"""
Export defined nodes to xml
"""
uris = await self.get_namespace_array()
uris_to_export = {}
for node in nodes:
idx = node.nodeid.NamespaceIndex
if idx not in uris_to_export and idx < len(uris):
uris_to_export[idx] = uris[idx]
exp = XmlExporter(self)
await exp.build_etree(nodes, uris_to_export)
await exp.build_etree(nodes)
await exp.write_xml(path)
async def export_xml_by_ns(self, path: str, namespaces: list = None):
......
......@@ -374,6 +374,10 @@ class SyncNode:
def read_attribute(self, attr):
pass
@syncmethod
def write_attribute(self, attributeid, datavalue, indexrange=None):
pass
@syncmethod
def read_browse_name(self):
pass
......
<?xml version='1.0' encoding='utf-8'?>
<UANodeSet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:uax="http://opcfoundation.org/UA/2008/02/Types.xsd" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://opcfoundation.org/UA/2011/03/UANodeSet.xsd">
<NamespaceUris>
<Uri>http://toto.freeopcua.github.io/</Uri>
</NamespaceUris>
<Aliases>
<Alias Alias="HasSubtype">i=45</Alias>
</Aliases>
<UADataType NodeId="ns=1;i=5101" BrowseName="4:MyCrazyEnum">
<DisplayName>MyCrazyEnum</DisplayName>
<Description>MyCrazyEnum</Description>
<Definition Name="MyCrazyEnum">
<Field Name="titi" Value="0" />
<Field Name="toto" Value="1" />
<Field Name="tutu" Value="2" />
</Definition>
<References>
<Reference ReferenceType="HasSubtype" IsForward="false">i=29</Reference>
</References>
</UADataType>
</UANodeSet>
<?xml version='1.0' encoding='utf-8'?>
<UANodeSet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:uax="http://opcfoundation.org/UA/2008/02/Types.xsd" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://opcfoundation.org/UA/2011/03/UANodeSet.xsd">
<NamespaceUris>
<Uri>http://toto.freeopcua.github.io/</Uri>
</NamespaceUris>
<Aliases>
<Alias Alias="HasEncoding">i=38</Alias>
<Alias Alias="HasSubtype">i=45</Alias>
</Aliases>
<UADataType NodeId="ns=1;i=6101" BrowseName="4:MyCrazyStruct">
<DisplayName>MyCrazyStruct</DisplayName>
<Description>My Description</Description>
<Definition Name="MyCrazyStruct">
<Field Name="MyBool" DataType="i=1" />
<Field Name="MyUInt32" DataType="i=7" ValueRank="0" ArrayDimensions="1" />
</Definition>
<References>
<Reference ReferenceType="HasSubtype" IsForward="false">i=22</Reference>
<Reference ReferenceType="HasEncoding">ns=1;i=6102</Reference>
</References>
</UADataType>
<UAObjectType NodeId="ns=1;i=6102" BrowseName="0:Default Binary">
<DisplayName>Default Binary</DisplayName>
<Description>Default Binary</Description>
<References>
<Reference ReferenceType="HasEncoding" IsForward="false">ns=1;i=6101</Reference>
</References>
</UAObjectType>
</UANodeSet>
......@@ -130,5 +130,5 @@ def test_sync_call_meth(client, idx):
def test_sync_xml_export(server):
exp = XmlExporter(server)
exp.build_etree([server.nodes.objects], uris=[])
exp.build_etree([server.nodes.objects])
exp.write_xml("toto_test_export.xml")
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment