About the Implementing an XML builder external component Sample
[C#]
XMLDocImpl.cs
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using ESRI.ArcGIS.Schematic;
using System.Windows.Forms;
namespace MyExtXmlComponentCS
{
[Guid("0CE2EC0B-975A-4795-A7C2-EF31978D92A2")]
[ClassInterface(ClassInterfaceType.None)]
[ProgId("MyExtXmlComponentCS.XMLDocImpl")]
public class XMLDocImpl : ISchematicXmlGenerate, ISchematicXmlUpdate
{
//
#region Variables
//This class must implement the ISchematicXMLGenerate and ISchematicXMLUpdate interfaces
private ESRI.ArcGIS.ArcMap.Application m_application; //ArcMap application
private ESRI.ArcGIS.ArcMapUI.IMxDocument m_mxDocument; //ArcMap document
//The following arrays will be used to create the wished propertyset properties in the XML DOMDocument
private string[] m_stationsPropertiesArray = { "Name", "Capacity", "Type", "Feeder" };
private string[] m_feedersPropertiesArray = { "Feeder_Description" };
private string[] m_LVLinesPropertiesArray = { "Category" };
private const string DatasetName = "ElectricDataSet";
~XMLDocImpl()
{
m_application = null;
m_mxDocument = null; ;
}
#endregion
#region ISchematicXmlGenerate Members
public void GenerateXmlData(string diagramName, string diagramClassName, ref object xmlSource, ref bool cancel)
{
MSXML2.DOMDocument xmlDOMDocument = new MSXML2.DOMDocument();
ESRI.ArcGIS.Carto.IMaps maps;
ESRI.ArcGIS.Carto.IMap currentMap;
ESRI.ArcGIS.Geodatabase.IEnumFeature enumFeature;
ESRI.ArcGIS.Geodatabase.IFeature feature;
MSXML2.IXMLDOMProcessingInstruction xmlProcInstr;
MSXML2.IXMLDOMElement xmlDiagrams;
MSXML2.IXMLDOMElement xmlDiagram;
MSXML2.IXMLDOMElement xmlFeatures;
MSXML2.IXMLDOMElement xmlDataSources;
MSXML2.IXMLDOMElement xmlDataSource;
MSXML2.IXMLDOMElement xmlDataSource_Namestring;
MSXML2.IXMLDOMElement xmlDataSource_WorkspaceInfo;
MSXML2.IXMLDOMElement xmlWorkspaceInfo_PathName;
MSXML2.IXMLDOMElement xmlWorkspaceInfo_WorkspaceFactoryProgID;
MSXML2.IXMLDOMAttribute rootAtt1;
MSXML2.IXMLDOMAttribute rootAtt2;
ESRI.ArcGIS.Geodatabase.IEnumFeatureSetup enumFeatureSetup;
string xmlDatabase;
// Retrieving the selected set of features
enumFeature = null;
feature = null;
m_mxDocument = (ESRI.ArcGIS.ArcMapUI.IMxDocument)m_application.Document;
maps = m_mxDocument.Maps;
int i = 0;
while (i < maps.Count)
{
currentMap = maps.get_Item(i);
enumFeature = (ESRI.ArcGIS.Geodatabase.IEnumFeature)currentMap.FeatureSelection;
enumFeatureSetup = (ESRI.ArcGIS.Geodatabase.IEnumFeatureSetup)enumFeature;
enumFeatureSetup.AllFields = true;
feature = enumFeature.Next();
if (feature != null) break;
i += 1;
}
// if (there is no selected feature in the MxDocument, the procedure is interrupted
if (feature == null)
{
MessageBox.Show("There is no feature selected. Select a set of features.", "Generate/Update XML diagrams", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
cancel = true;
return;
}
//Checking the feature dataset related to the selected features
ESRI.ArcGIS.Geodatabase.IFeatureClass featureClass;
string featureDatasetName;
featureClass = (ESRI.ArcGIS.Geodatabase.IFeatureClass)feature.Class;
featureDatasetName = featureClass.FeatureDataset.BrowseName;
xmlDatabase = featureClass.FeatureDataset.Workspace.PathName;
// if the selected features come from another feature dataset than the expected one, the procedure is interrupted
if (featureDatasetName != DatasetName)
{
//More restrictive condition: if (xmlDatabase != "c:\Mybase.gdb" )
MessageBox.Show("This component doesn't work from the selected set of features.");
cancel = true;
return;
}
// Writing the XML heading items in the DOMDocument
xmlProcInstr = xmlDOMDocument.createProcessingInstruction("xml", "version='1.0'");
xmlDOMDocument.appendChild(xmlProcInstr);
xmlProcInstr = null;
//-------- Diagrams Section START --------
// Creating the root Diagrams element
xmlDiagrams = xmlDOMDocument.createElement("Diagrams");
xmlDOMDocument.documentElement = xmlDiagrams;
rootAtt1 = xmlDOMDocument.createAttribute("xmlns:xsi");
rootAtt1.text = "http://www.w3.org/2001/XMLSchema-instance";
xmlDiagrams.attributes.setNamedItem(rootAtt1);
// Creating the Diagram element for the diagram which is going to be generated
xmlDiagram = xmlDOMDocument.createElement("Diagram");
xmlDiagrams.appendChild(xmlDiagram);
rootAtt1 = xmlDOMDocument.createAttribute("EnforceDiagramTemplateName");
rootAtt1.text = "false";
xmlDiagram.attributes.setNamedItem(rootAtt1);
rootAtt2 = xmlDOMDocument.createAttribute("EnforceDiagramName");
rootAtt2.text = "false";
xmlDiagram.attributes.setNamedItem(rootAtt2);
//-------- DataSources Section START --------
// Creating the DataSources element
xmlDataSources = xmlDOMDocument.createElement("Datasources");
xmlDiagram.appendChild(xmlDataSources);
xmlDataSource = xmlDOMDocument.createElement("Datasource");
xmlDataSources.appendChild(xmlDataSource);
// Specifying the Namestring for the related Datasource element
xmlDataSource_Namestring = xmlDOMDocument.createElement("NameString");
xmlDataSource.appendChild(xmlDataSource_Namestring);
xmlDataSource_Namestring.nodeTypedValue = "XMLDataSource";
// Specifying the WorkspaceInfo for the related Datasource element
xmlDataSource_WorkspaceInfo = xmlDOMDocument.createElement("WorkSpaceInfo");
xmlDataSource.appendChild(xmlDataSource_WorkspaceInfo);
xmlWorkspaceInfo_PathName = xmlDOMDocument.createElement("PathName");
xmlDataSource_WorkspaceInfo.appendChild(xmlWorkspaceInfo_PathName);
xmlWorkspaceInfo_PathName.nodeTypedValue = xmlDatabase;
xmlWorkspaceInfo_WorkspaceFactoryProgID = xmlDOMDocument.createElement("WorkspaceFactoryProgID");
xmlDataSource_WorkspaceInfo.appendChild(xmlWorkspaceInfo_WorkspaceFactoryProgID);
xmlWorkspaceInfo_WorkspaceFactoryProgID.nodeTypedValue = "esriDataSourcesGDB.FileGDBWorkspaceFactory";
//-------- DataSources Section END --------
//-------- Features Section START --------
xmlFeatures = xmlDOMDocument.createElement("Features");
xmlDiagram.appendChild(xmlFeatures);
while (feature != null)
{
switch (feature.FeatureType)
{
case ESRI.ArcGIS.Geodatabase.esriFeatureType.esriFTSimpleJunction:
CreateXMLNodeElt(feature, ref xmlDOMDocument, ref xmlFeatures, feature.Class.AliasName);
break;
case ESRI.ArcGIS.Geodatabase.esriFeatureType.esriFTSimpleEdge:
CreateXMLLinkElt(feature, ref xmlDOMDocument, ref xmlFeatures, feature.Class.AliasName);
break;
}
feature = enumFeature.Next();
}
// output the XML we created
xmlSource = xmlDOMDocument;
cancel = false;
//-------- Features Section END --------
//-------- Diagrams Section END --------
}
#endregion
#region ISchematicXmlUpdate Members
public void UpdateXmlData(string diagramName, string diagramClassName, string updateInformation, ref object xmlSource, ref bool cancel)
{
GenerateXmlData(diagramName, diagramClassName, ref xmlSource, ref cancel);
}
#endregion
#region "private functions"
// The following CreateXMLLNodeElt private procedure is used to create all the expected
// XML items for a XML NodeFeature related to a Station or Feeder simple junction feature
private void CreateXMLNodeElt(ESRI.ArcGIS.Geodatabase.IFeature inFeature, ref MSXML2.DOMDocument outDOMDoc, ref MSXML2.IXMLDOMElement outXMLElements, string inNodeTypeName)
{
if (!inFeature.HasOID)
{
MessageBox.Show("No OID");
return;
}
MSXML2.IXMLDOMElement xmlNode;
MSXML2.IXMLDOMElement xmlNode_XCoord;
MSXML2.IXMLDOMElement xmlNode_YCoord;
MSXML2.IXMLDOMElement xmlNode_RelatedContainerID;
bool relatedContainer;
MSXML2.IXMLDOMNodeList xmlNodeList;
MSXML2.IXMLDOMElement xmlDrawing;
MSXML2.IXMLDOMElement xmlDrawing_EltTypeName;
MSXML2.IXMLDOMElement xmlDrawing_ExternalUID;
//-------- Feature Section START related to the "infeature" --------
// Creating the NodeFeature element
xmlNode = outDOMDoc.createElement("NodeFeature");
outXMLElements.appendChild(xmlNode);
// Specifying basic XML items for this NodeFeature
CreateBasicXMLItemsForSchematicElt(inFeature, ref outDOMDoc, ref xmlNode, inNodeTypeName);
// Specifying its X && Y when they exist
if ((inFeature.Fields.FindField("X") > 0) && (inFeature.Fields.FindField("Y") > 0))
{
// Specifying InitialX
xmlNode_XCoord = outDOMDoc.createElement("InitialX");
xmlNode.appendChild(xmlNode_XCoord);
xmlNode_XCoord.nodeTypedValue = inFeature.get_Value(inFeature.Fields.FindField("X"));
// Specifying InitialY
xmlNode_YCoord = outDOMDoc.createElement("InitialY");
xmlNode.appendChild(xmlNode_YCoord);
xmlNode_YCoord.nodeTypedValue = inFeature.get_Value(inFeature.Fields.FindField("Y"));
}
else
{
// Retrieving initial position from Geometry
ESRI.ArcGIS.Geometry.IPoint oPoint = (ESRI.ArcGIS.Geometry.IPoint)inFeature.ShapeCopy;
if (oPoint != null)
{
// Specifying InitialX
xmlNode_XCoord = outDOMDoc.createElement("InitialX");
xmlNode.appendChild(xmlNode_XCoord);
xmlNode_XCoord.nodeTypedValue = oPoint.X;
// Specifying InitialY
xmlNode_YCoord = outDOMDoc.createElement("InitialY");
xmlNode.appendChild(xmlNode_YCoord);
xmlNode_YCoord.nodeTypedValue = oPoint.Y;
}
}
xmlNode_RelatedContainerID = outDOMDoc.createElement("RelatedContainerID");
xmlNode.appendChild(xmlNode_RelatedContainerID);
// Specifying its properties
switch (inFeature.Class.AliasName)
{
case "Station":
{
xmlNode_RelatedContainerID.nodeTypedValue = "Container-" + System.Convert.ToString(inFeature.get_Value(inFeature.Fields.FindField("Feeder")));
// For Station feature, the field contained in the StationsPropertiesArray will be exported
CompleteXMLEltByProperties(inFeature, ref outDOMDoc, ref xmlNode, m_stationsPropertiesArray);
break;
}
case "Feeder":
{
xmlNode_RelatedContainerID.nodeTypedValue = "Container-" + inFeature.OID.ToString();
// For Feeder feature, the field contained in the StationsPropertiesArray will be exported
CompleteXMLEltByProperties(inFeature, ref outDOMDoc, ref xmlNode, m_feedersPropertiesArray);
break;
}
}
//-------- Feature Section END related to the "infeature" --------
// Checking the existence of the related container
xmlNodeList = outXMLElements.selectNodes("NodeFeature/ExternalUniqueID");
relatedContainer = false;
foreach (MSXML2.IXMLDOMNode node in xmlNodeList)
{
if (node.text == xmlNode_RelatedContainerID.nodeTypedValue.ToString())
{
relatedContainer = true;
break;
}
} // pNode
// Creating the related container when it doesn//t already exist
if (!relatedContainer)
{
xmlDrawing = outDOMDoc.createElement("NodeFeature");
outXMLElements.appendChild(xmlDrawing);
// Specifying its FeatureClassName
xmlDrawing_EltTypeName = outDOMDoc.createElement("FeatureClassName");
xmlDrawing.appendChild(xmlDrawing_EltTypeName);
xmlDrawing_EltTypeName.nodeTypedValue = "Containers";
// Specifying its ExternalUniqueID
xmlDrawing_ExternalUID = outDOMDoc.createElement("ExternalUniqueID");
xmlDrawing.appendChild(xmlDrawing_ExternalUID);
xmlDrawing_ExternalUID.nodeTypedValue = xmlNode_RelatedContainerID.nodeTypedValue;
}
}
// The following CreateXMLLinkElt private procedure is used to create all the expected XML items for a XML LinkFeature related to a HV_Line or LV_Line simple edge feature
private void CreateXMLLinkElt(ESRI.ArcGIS.Geodatabase.IFeature inFeature, ref MSXML2.DOMDocument outDOMDoc, ref MSXML2.IXMLDOMElement outXMLElements, string inLinkTypeName)
{
if (!inFeature.HasOID)
{
MessageBox.Show("No OID");
return;
}
MSXML2.IXMLDOMElement xmlLink;
MSXML2.IXMLDOMElement xmlLink_FromNode;
MSXML2.IXMLDOMElement xmlLink_ToNode;
int indexListPoints;
string listPoints;
int nbVertices;
string vertices;
MSXML2.IXMLDOMElement xmlLink_Vertices;
MSXML2.IXMLDOMElement xmlLink_Vertex;
MSXML2.IXMLDOMElement xmlLink_XVertex;
MSXML2.IXMLDOMElement xmlLink_YVertex;
string xValue;
string yValue;
//-------- Feature Section START related to the "infeature" --------
// Creating the LinkFeature Feature
xmlLink = outDOMDoc.createElement("LinkFeature");
outXMLElements.appendChild(xmlLink);
// Specifying basic XML items for this LinkFeature
CreateBasicXMLItemsForSchematicElt(inFeature, ref outDOMDoc, ref xmlLink, inLinkTypeName);
// Specifying its FromNode
xmlLink_FromNode = outDOMDoc.createElement("FromNode");
xmlLink.appendChild(xmlLink_FromNode);
xmlLink_FromNode.nodeTypedValue = inFeature.get_Value(inFeature.Fields.FindField("FromJunctionType")) + "-" + inFeature.get_Value(inFeature.Fields.FindField("FromJunctionOID"));
// Specifying its ToNode
xmlLink_ToNode = outDOMDoc.createElement("ToNode");
xmlLink.appendChild(xmlLink_ToNode);
xmlLink_ToNode.nodeTypedValue = inFeature.get_Value(inFeature.Fields.FindField("ToJunctionType")) + "-" + inFeature.get_Value(inFeature.Fields.FindField("ToJunctionOID"));
//Add Vertices to LinkFeature ---- NEED TO BE COMPLETED
indexListPoints = inFeature.Fields.FindField("ListPoints");
if (indexListPoints > 0)
{
listPoints = "";
listPoints = inFeature.get_Value(indexListPoints).ToString();
if (listPoints != "")
{
int foundChar = listPoints.IndexOf(";", 1);
nbVertices = System.Convert.ToInt32(listPoints.Substring(0, foundChar));
vertices = listPoints.Substring(foundChar + 1);
if (nbVertices > 0)
{
// Specifying its Vertices
xmlLink_Vertices = outDOMDoc.createElement("Vertices");
xmlLink.appendChild(xmlLink_Vertices);
int iLoc;
for (int i = 1; i <= nbVertices; i++)
{
xValue = "";
yValue = "";
iLoc = vertices.IndexOf(";", 1);
if (vertices != "" && (iLoc) > 0)
{
xValue = vertices.Substring(0, iLoc);
}
vertices = vertices.Substring(iLoc + 1);
iLoc = vertices.IndexOf(";", 1);
if (vertices != ";" && (iLoc) > 0)
{
yValue = vertices.Substring(0, iLoc);
}
if (xValue != "" && yValue != "")
{
xmlLink_Vertex = outDOMDoc.createElement("Vertex");
xmlLink_Vertices.appendChild(xmlLink_Vertex);
xmlLink_XVertex = outDOMDoc.createElement("X");
xmlLink_Vertex.appendChild(xmlLink_XVertex);
xmlLink_XVertex.nodeTypedValue = xValue;
xmlLink_YVertex = outDOMDoc.createElement("Y");
xmlLink_Vertex.appendChild(xmlLink_YVertex);
xmlLink_YVertex.nodeTypedValue = yValue;
if (vertices.Length - iLoc > 0)
{
vertices = vertices.Substring(iLoc + 1); //sVertices.Length - iLoc)
}
else
{
break;
}
}
else
{
break;
}
}
}
}
}
else
{// Retrieving ListPoint from geometry
ESRI.ArcGIS.Geometry.IPolyline oPoly = (ESRI.ArcGIS.Geometry.IPolyline)inFeature.ShapeCopy;
ESRI.ArcGIS.Geometry.IPointCollection colLink = (ESRI.ArcGIS.Geometry.IPointCollection)oPoly;
if (colLink != null && colLink.PointCount > 2)
{
ESRI.ArcGIS.Geometry.IPoint oPoint;
xmlLink_Vertices = outDOMDoc.createElement("Vertices");
xmlLink.appendChild(xmlLink_Vertices);
for (int i = 1; i < colLink.PointCount - 1; i++)
{
oPoint = colLink.get_Point(i);
xmlLink_Vertex = outDOMDoc.createElement("Vertex");
xmlLink_Vertices.appendChild(xmlLink_Vertex);
xmlLink_XVertex = outDOMDoc.createElement("X");
xmlLink_Vertex.appendChild(xmlLink_XVertex);
xmlLink_XVertex.nodeTypedValue = oPoint.X;
xmlLink_YVertex = outDOMDoc.createElement("Y");
xmlLink_Vertex.appendChild(xmlLink_YVertex);
xmlLink_YVertex.nodeTypedValue = oPoint.Y;
}
}
}
//Specifying its properties
switch (inFeature.Class.AliasName)
{
case "LV_Line":
{
CompleteXMLEltByProperties(inFeature, ref outDOMDoc, ref xmlLink, m_LVLinesPropertiesArray);
break;
}
}
//-------- Feature Section END related to the "infeature" --------
}
// The following CreateBasicXMLItmesForSchematicElt private procedure is used to create the first expected XML items for a XML NodeFeature or LinkFeature
private void CreateBasicXMLItemsForSchematicElt(ESRI.ArcGIS.Geodatabase.IFeature inFeature,
ref MSXML2.DOMDocument outDOMDoc,
ref MSXML2.IXMLDOMElement outXMLElement,
string inEltTypeName)
{
MSXML2.IXMLDOMElement xmlElt_EltTypeName;
MSXML2.IXMLDOMElement xmlElt_ExternalUID;
MSXML2.IXMLDOMElement xmlElt_DatasourceName;
MSXML2.IXMLDOMElement xmlElt_UCID;
MSXML2.IXMLDOMElement xmlElt_UOID;
// Specifying its FeatureClassName
xmlElt_EltTypeName = outDOMDoc.createElement("FeatureClassName");
outXMLElement.appendChild(xmlElt_EltTypeName);
if (inFeature.Fields.FindField("Feeder") != -1)
{
xmlElt_EltTypeName.nodeTypedValue = inEltTypeName + "sFeeder" + inFeature.get_Value(inFeature.Fields.FindField("Feeder")).ToString();
}
else
{
xmlElt_EltTypeName.nodeTypedValue = inEltTypeName + "s";
}
// Specifying its ExternalUniqueID
xmlElt_ExternalUID = outDOMDoc.createElement("ExternalUniqueID");
outXMLElement.appendChild(xmlElt_ExternalUID);
xmlElt_ExternalUID.nodeTypedValue = inEltTypeName + "-" + inFeature.OID.ToString();
// Specifying its DatasourceName
xmlElt_DatasourceName = outDOMDoc.createElement("DatasourceName");
outXMLElement.appendChild(xmlElt_DatasourceName);
xmlElt_DatasourceName.nodeTypedValue = "XMLDataSource";
// Specifying its UCID
xmlElt_UCID = outDOMDoc.createElement("UCID");
outXMLElement.appendChild(xmlElt_UCID);
xmlElt_UCID.nodeTypedValue = inFeature.Class.ObjectClassID;
// Add UOID to NodeElement
xmlElt_UOID = outDOMDoc.createElement("UOID");
outXMLElement.appendChild(xmlElt_UOID);
xmlElt_UOID.nodeTypedValue = inFeature.OID;
}
// The following CompleteXMLEltByProperties private procedure is used to create all the expected propertyset properties listed in the input PropertiesArray array
private void CompleteXMLEltByProperties(ESRI.ArcGIS.Geodatabase.IFeature inFeature,
ref MSXML2.DOMDocument outDOMDoc,
ref MSXML2.IXMLDOMElement outXMLElement,
string[] propertiesArray)
{
int i = 0;
MSXML2.IXMLDOMElement xmlPropertySet;
MSXML2.IXMLDOMElement xmlPropertyArray;
MSXML2.IXMLDOMElement xmlPropertySetProperty;
MSXML2.IXMLDOMElement xmlProperty_Key;
MSXML2.IXMLDOMElement xmlProperty_Value;
if (propertiesArray.Length > 0)
{
//-------- PropertySet Section START --------
// Creating the PropertySet element for the input outXMLElement
xmlPropertySet = outDOMDoc.createElement("PropertySet");
outXMLElement.appendChild(xmlPropertySet);
// Creating the PropertyArray element
xmlPropertyArray = outDOMDoc.createElement("PropertyArray");
xmlPropertySet.appendChild(xmlPropertyArray);
while (i < propertiesArray.Length)
{
// Creating the i PropertySetProperty
xmlPropertySetProperty = outDOMDoc.createElement("PropertySetProperty");
xmlPropertyArray.appendChild(xmlPropertySetProperty);
// Specifying the key && value field related to that i PropertySetProperty
xmlProperty_Key = outDOMDoc.createElement("Key");
xmlPropertySetProperty.appendChild(xmlProperty_Key);
xmlProperty_Key.nodeTypedValue = propertiesArray[i].ToString();
xmlProperty_Value = outDOMDoc.createElement("Value");
xmlPropertySetProperty.appendChild(xmlProperty_Value);
xmlProperty_Value.nodeTypedValue = inFeature.get_Value(inFeature.Fields.FindField(propertiesArray[i].ToString()));
i += 1;
}
}
//-------- PropertySet Section END --------
}
#endregion
public object ApplicationHook
{
get
{
return (object)m_application;
}
set
{
m_application = (ESRI.ArcGIS.ArcMap.Application)value;
}
}
}
}
[Visual Basic .NET]
XMLDocImpl.vb
Imports System.Collections.Generic
Imports System.Text
Imports System.Runtime.InteropServices
Imports ESRI.ArcGIS.Schematic
Imports System.Windows.Forms
<Guid("A87C1C4A-1827-45e7-980B-4A5C781CF404")> _
<ClassInterface(ClassInterfaceType.None)> _
<ProgId("MyExtXmlComponentVB.XMLDocImpl")> _
Public Class XMLDocImpl
Implements ISchematicXmlGenerate
Implements ISchematicXmlUpdate
'
#Region "Variables"
'This class must implement the ISchematicXMLGenerate & ISchematicXMLUpdate interfaces
Private m_application As ESRI.ArcGIS.ArcMap.Application ' ArcMap application
Private m_mxDocument As ESRI.ArcGIS.ArcMapUI.IMxDocument ' ArcMap document
Private installationFolder As String
'The following arrays will be used to create the wished propertyset properties in the XML DOMDocument
Private m_stationsPropertiesArray() As String = {"Name", "Capacity", "Type", "Feeder"}
Private m_feedersPropertiesArray() As String = {"Feeder_Description"}
Private m_LVLinesPropertiesArray() As String = {"Category"}
Private Const DatasetName As String = "ElectricDataSet"
Protected Overrides Sub Finalize()
m_application = Nothing
m_mxDocument = Nothing
MyBase.Finalize()
End Sub
#End Region
#Region "ISchematicXmlGenerate Members"
Public Sub GenerateXmlData(ByVal diagramName As String, ByVal diagramClassName As String, ByRef xmlSource As Object, ByRef cancel As Boolean) Implements ISchematicXmlGenerate.GenerateXmlData
Dim xmlDocument As MSXML2.DOMDocument = New MSXML2.DOMDocument()
Dim maps As ESRI.ArcGIS.Carto.IMaps
Dim currentMap As ESRI.ArcGIS.Carto.IMap
Dim enumFeature As ESRI.ArcGIS.Geodatabase.IEnumFeature
Dim feature As ESRI.ArcGIS.Geodatabase.IFeature
Dim xmlProcInstr As MSXML2.IXMLDOMProcessingInstruction
Dim xmlDiagrams As MSXML2.IXMLDOMElement
Dim xmlDiagram As MSXML2.IXMLDOMElement
Dim xmlFeatures As MSXML2.IXMLDOMElement
Dim xmlDataSources As MSXML2.IXMLDOMElement
Dim xmlDataSource As MSXML2.IXMLDOMElement
Dim xmlDataSource_NameString As MSXML2.IXMLDOMElement
Dim xmlDataSource_WorkspaceInfo As MSXML2.IXMLDOMElement
Dim xmlWorkspaceInfo_PathName As MSXML2.IXMLDOMElement
Dim xmlWorkspaceInfo_WorkspaceFactoryProgID As MSXML2.IXMLDOMElement
Dim rootAtt1 As MSXML2.IXMLDOMAttribute
Dim rootAtt2 As MSXML2.IXMLDOMAttribute
Dim enumFeatureSetup As ESRI.ArcGIS.Geodatabase.IEnumFeatureSetup
Dim xmlDatabase As String
' Retrieving the selected set of features
enumFeature = Nothing
feature = Nothing
m_mxDocument = CType(m_application.Document, ESRI.ArcGIS.ArcMapUI.IMxDocument)
maps = m_mxDocument.Maps
Dim i As Integer = 0
While (i < maps.Count)
currentMap = maps.Item(i)
enumFeature = CType(currentMap.FeatureSelection, ESRI.ArcGIS.Geodatabase.IEnumFeature)
enumFeatureSetup = CType(enumFeature, ESRI.ArcGIS.Geodatabase.IEnumFeatureSetup)
enumFeatureSetup.AllFields = True
feature = enumFeature.Next()
If (feature IsNot Nothing) Then Exit While
i += 1
End While
' if (there is no selected feature in the MxDocument, the procedure is interrupted
If (feature Is Nothing) Then
MsgBox("There is no feature selected. Select a set of features.", "Generate/Update XML diagrams", MsgBoxStyle.OkOnly + MsgBoxStyle.Exclamation)
cancel = True
Return
End If
'Checking the feature dataset related to the selected features
Dim featureClass As ESRI.ArcGIS.Geodatabase.IFeatureClass
Dim featureDatasetName As String
featureClass = CType(feature.Class, ESRI.ArcGIS.Geodatabase.IFeatureClass)
featureDatasetName = featureClass.FeatureDataset.BrowseName
xmlDatabase = featureClass.FeatureDataset.Workspace.PathName
' if the selected features come from another feature dataset than the expected one, the procedure is interrupted
If (featureDatasetName <> DatasetName) Then
'More restrictive condition: If (xmlDatabase <> "c:\Mybase.gdb") Then
MsgBox("This component doesn't work from the selected set of features.")
cancel = True
Return
End If
' Writing the XML heading items in the DOMDocument
xmlProcInstr = xmlDocument.createProcessingInstruction("xml", "version='1.0'")
xmlDocument.appendChild(xmlProcInstr)
xmlProcInstr = Nothing
'-------- Diagrams Section START --------
' Creating the root Diagrams element
xmlDiagrams = xmlDocument.createElement("Diagrams")
xmlDocument.documentElement = xmlDiagrams
rootAtt1 = xmlDocument.createAttribute("xmlns:xsi")
rootAtt1.text = "http://www.w3.org/2001/XMLSchema-instance"
xmlDiagrams.attributes.setNamedItem(rootAtt1)
'rootAtt2 = xmlDocument.createAttribute("xsi:noNamespaceSchemaLocation")
'rootAtt2.text = XmlSchema
'xmlDiagrams.attributes.setNamedItem(rootAtt2)
' Creating the Diagram element for the diagram which is going to be generated
xmlDiagram = xmlDocument.createElement("Diagram")
xmlDiagrams.appendChild(xmlDiagram)
rootAtt1 = xmlDocument.createAttribute("EnforceDiagramTemplateName")
rootAtt1.text = "false"
xmlDiagram.attributes.setNamedItem(rootAtt1)
rootAtt2 = xmlDocument.createAttribute("EnforceDiagramName")
rootAtt2.text = "false"
xmlDiagram.attributes.setNamedItem(rootAtt2)
'-------- DataSources Section START --------
' Creating the DataSources element
xmlDataSources = xmlDocument.createElement("Datasources")
xmlDiagram.appendChild(xmlDataSources)
xmlDataSource = xmlDocument.createElement("Datasource")
xmlDataSources.appendChild(xmlDataSource)
' Specifying the Namestring for the related Datasource element
xmlDataSource_NameString = xmlDocument.createElement("NameString")
xmlDataSource.appendChild(xmlDataSource_NameString)
xmlDataSource_NameString.nodeTypedValue = "XMLDataSource"
' Specifying the WorkspaceInfo for the related Datasource element
xmlDataSource_WorkspaceInfo = xmlDocument.createElement("WorkSpaceInfo")
xmlDataSource.appendChild(xmlDataSource_WorkspaceInfo)
xmlWorkspaceInfo_PathName = xmlDocument.createElement("PathName")
xmlDataSource_WorkspaceInfo.appendChild(xmlWorkspaceInfo_PathName)
xmlWorkspaceInfo_PathName.nodeTypedValue = xmlDatabase
xmlWorkspaceInfo_WorkspaceFactoryProgID = xmlDocument.createElement("WorkspaceFactoryProgID")
xmlDataSource_WorkspaceInfo.appendChild(xmlWorkspaceInfo_WorkspaceFactoryProgID)
xmlWorkspaceInfo_WorkspaceFactoryProgID.nodeTypedValue = "esriDataSourcesGDB.FileGDBWorkspaceFactory"
'-------- DataSources Section END --------
'-------- Features Section START --------
xmlFeatures = xmlDocument.createElement("Features")
xmlDiagram.appendChild(xmlFeatures)
While (feature IsNot Nothing)
Select Case (feature.FeatureType)
Case ESRI.ArcGIS.Geodatabase.esriFeatureType.esriFTSimpleJunction
CreateXMLNodeElt(feature, xmlDocument, xmlFeatures, feature.Class.AliasName)
Case ESRI.ArcGIS.Geodatabase.esriFeatureType.esriFTSimpleEdge
CreateXMLLinkElt(feature, xmlDocument, xmlFeatures, feature.Class.AliasName)
End Select
feature = enumFeature.Next()
End While
' output the XML we created
xmlSource = xmlDocument
cancel = False
'-------- Features Section END --------
'-------- Diagrams Section END --------
End Sub
Public Property ApplicationHook() As Object Implements ISchematicXmlGenerate.ApplicationHook
Get
Return CType(m_application, Object)
End Get
Set(ByVal value As Object)
m_application = CType(value, ESRI.ArcGIS.ArcMap.Application)
End Set
End Property
#End Region
#Region "ISchematicXmlUpdate Members"
Public Sub UpdateXmlData(ByVal diagramName As String, ByVal diagramClassName As String, ByVal updateInformation As String, ByRef xmlSource As Object, ByRef cancel As Boolean) Implements ISchematicXmlUpdate.UpdateXmlData
GenerateXmlData(diagramName, diagramClassName, xmlSource, cancel)
End Sub
Public Property ApplicationHook1() As Object Implements ISchematicXmlUpdate.ApplicationHook
Get
Return CType(m_application, Object)
End Get
Set(ByVal value As Object)
m_application = CType(value, ESRI.ArcGIS.ArcMap.Application)
End Set
End Property
#End Region
#Region "private functions"
' The following CreateXMLLNodeElt private procedure is used to create all the expected
' XML items for a XML NodeFeature related to a Station or Feeder simple junction feature
Private Sub CreateXMLNodeElt(ByVal inFeature As ESRI.ArcGIS.Geodatabase.IFeature, ByRef outDOMDoc As MSXML2.DOMDocument, ByRef outXMLElements As MSXML2.IXMLDOMElement, ByVal inNodeTypeName As String)
If (Not inFeature.HasOID) Then
MsgBox("No OID")
Return
End If
Dim xmlNode As MSXML2.IXMLDOMElement
Dim xmlNode_XCoord As MSXML2.IXMLDOMElement
Dim xmlNode_YCoord As MSXML2.IXMLDOMElement
Dim xmlNode_RelatedContainerID As MSXML2.IXMLDOMElement
Dim relatedContainer As Boolean
Dim xmlNodeList As MSXML2.IXMLDOMNodeList
Dim xmlDrawing As MSXML2.IXMLDOMElement
Dim xmlDrawing_EltTypeName As MSXML2.IXMLDOMElement
Dim xmlDrawing_ExternalUID As MSXML2.IXMLDOMElement
'-------- Feature Section START related to the "infeature" --------
' Creating the NodeFeature element
xmlNode = outDOMDoc.createElement("NodeFeature")
outXMLElements.appendChild(xmlNode)
' Specifying basic XML items for this NodeFeature
CreateBasicXMLItemsForSchematicElt(inFeature, outDOMDoc, xmlNode, inNodeTypeName)
' Specifying its X && Y when they exist
If ((inFeature.Fields.FindField("X") > 0) AndAlso (inFeature.Fields.FindField("Y") > 0)) Then
' Specifying InitialX
xmlNode_XCoord = outDOMDoc.createElement("InitialX")
xmlNode.appendChild(xmlNode_XCoord)
xmlNode_XCoord.nodeTypedValue = inFeature.Value(inFeature.Fields.FindField("X"))
' Specifying InitialY
xmlNode_YCoord = outDOMDoc.createElement("InitialY")
xmlNode.appendChild(xmlNode_YCoord)
xmlNode_YCoord.nodeTypedValue = inFeature.Value(inFeature.Fields.FindField("Y"))
Else
' Retrieving initial position from Geometry
Dim oPoint As ESRI.ArcGIS.Geometry.IPoint = TryCast(inFeature.ShapeCopy, ESRI.ArcGIS.Geometry.IPoint)
If (oPoint IsNot Nothing) Then
' Specifying InitialX
xmlNode_XCoord = outDOMDoc.createElement("InitialX")
xmlNode.appendChild(xmlNode_XCoord)
xmlNode_XCoord.nodeTypedValue = oPoint.X
' Specifying InitialY
xmlNode_YCoord = outDOMDoc.createElement("InitialY")
xmlNode.appendChild(xmlNode_YCoord)
xmlNode_YCoord.nodeTypedValue = oPoint.Y
End If
End If
xmlNode_RelatedContainerID = outDOMDoc.createElement("RelatedContainerID")
xmlNode.appendChild(xmlNode_RelatedContainerID)
' Specifying its properties
Select Case (inFeature.Class.AliasName)
Case "Station"
xmlNode_RelatedContainerID.nodeTypedValue = "Container-" & System.Convert.ToString(inFeature.Value(inFeature.Fields.FindField("Feeder")))
' For Station feature, the field contained in the StationsPropertiesArray will be exported
CompleteXMLEltByProperties(inFeature, outDOMDoc, xmlNode, m_stationsPropertiesArray)
Case "Feeder"
xmlNode_RelatedContainerID.nodeTypedValue = "Container-" & inFeature.OID.ToString()
' For Feeder feature, the field contained in the StationsPropertiesArray will be exported
CompleteXMLEltByProperties(inFeature, outDOMDoc, xmlNode, m_feedersPropertiesArray)
End Select
'-------- Feature Section END related to the "infeature" --------
' Checking the existence of the related container
xmlNodeList = outXMLElements.selectNodes("NodeFeature/ExternalUniqueID")
relatedContainer = False
For Each node As MSXML2.IXMLDOMNode In xmlNodeList
If (node.text = xmlNode_RelatedContainerID.nodeTypedValue.ToString()) Then
relatedContainer = True
Exit For
End If
Next ' pNode
' Creating the related container when it doesn//t already exist
If (Not relatedContainer) Then
xmlDrawing = outDOMDoc.createElement("NodeFeature")
outXMLElements.appendChild(xmlDrawing)
' Specifying its FeatureClassName
xmlDrawing_EltTypeName = outDOMDoc.createElement("FeatureClassName")
xmlDrawing.appendChild(xmlDrawing_EltTypeName)
xmlDrawing_EltTypeName.nodeTypedValue = "Containers"
' Specifying its ExternalUniqueID
xmlDrawing_ExternalUID = outDOMDoc.createElement("ExternalUniqueID")
xmlDrawing.appendChild(xmlDrawing_ExternalUID)
xmlDrawing_ExternalUID.nodeTypedValue = xmlNode_RelatedContainerID.nodeTypedValue
End If
End Sub
' The following CreateXMLLinkElt private procedure is used to create all the expected XML items for a XML LinkFeature related to a HV_Line or LV_Line simple edge feature
Private Sub CreateXMLLinkElt(ByVal inFeature As ESRI.ArcGIS.Geodatabase.IFeature, ByRef outDOMDoc As MSXML2.DOMDocument, ByRef outXMLElements As MSXML2.IXMLDOMElement, ByVal inLinkTypeName As String)
If (Not inFeature.HasOID) Then
MessageBox.Show("No OID")
Return
End If
Dim xmlLink As MSXML2.IXMLDOMElement
Dim xmlLink_FromNode As MSXML2.IXMLDOMElement
Dim xmlLink_ToNode As MSXML2.IXMLDOMElement
Dim indexListPoints As Integer
Dim listPoints As String
Dim nbVertices As Integer
Dim vertices As String
Dim xmlLink_Vertices As MSXML2.IXMLDOMElement
Dim xmlLink_Vertex As MSXML2.IXMLDOMElement
Dim xmlLink_XVertex As MSXML2.IXMLDOMElement
Dim xmlLink_YVertex As MSXML2.IXMLDOMElement
Dim xValue As String
Dim yValue As String
'-------- Feature Section START related to the "infeature" --------
' Creating the LinkFeature Feature
xmlLink = outDOMDoc.createElement("LinkFeature")
outXMLElements.appendChild(xmlLink)
' Specifying basic XML items for this LinkFeature
CreateBasicXMLItemsForSchematicElt(inFeature, outDOMDoc, xmlLink, inLinkTypeName)
' Specifying its FromNode
xmlLink_FromNode = outDOMDoc.createElement("FromNode")
xmlLink.appendChild(xmlLink_FromNode)
xmlLink_FromNode.nodeTypedValue = inFeature.Value(inFeature.Fields.FindField("FromJunctionType")) & "-" & inFeature.Value(inFeature.Fields.FindField("FromJunctionOID"))
' Specifying its ToNode
xmlLink_ToNode = outDOMDoc.createElement("ToNode")
xmlLink.appendChild(xmlLink_ToNode)
xmlLink_ToNode.nodeTypedValue = inFeature.Value(inFeature.Fields.FindField("ToJunctionType")) & "-" & inFeature.Value(inFeature.Fields.FindField("ToJunctionOID"))
'Add Vertices to LinkFeature ---- NEED TO BE COMPLETED
indexListPoints = inFeature.Fields.FindField("ListPoints")
If (indexListPoints > 0) Then
listPoints = ""
listPoints = inFeature.Value(indexListPoints).ToString()
If (listPoints <> "") Then
Dim foundChar As Integer = listPoints.IndexOf(";", 1)
nbVertices = System.Convert.ToInt32(listPoints.Substring(0, foundChar))
vertices = listPoints.Substring(foundChar + 1)
If (nbVertices > 0) Then
' Specifying its Vertices
xmlLink_Vertices = outDOMDoc.createElement("Vertices")
xmlLink.appendChild(xmlLink_Vertices)
Dim iLoc As Integer
For i As Integer = 1 To nbVertices
xValue = ""
yValue = ""
iLoc = vertices.IndexOf(";", 1)
If (vertices <> "" AndAlso (iLoc) > 0) Then
xValue = vertices.Substring(0, iLoc)
End If
vertices = vertices.Substring(iLoc + 1)
iLoc = vertices.IndexOf(";", 1)
If (vertices <> ";" AndAlso (iLoc) > 0) Then
yValue = vertices.Substring(0, iLoc)
End If
If (xValue <> "" AndAlso yValue <> "") Then
xmlLink_Vertex = outDOMDoc.createElement("Vertex")
xmlLink_Vertices.appendChild(xmlLink_Vertex)
xmlLink_XVertex = outDOMDoc.createElement("X")
xmlLink_Vertex.appendChild(xmlLink_XVertex)
xmlLink_XVertex.nodeTypedValue = xValue
xmlLink_YVertex = outDOMDoc.createElement("Y")
xmlLink_Vertex.appendChild(xmlLink_YVertex)
xmlLink_YVertex.nodeTypedValue = yValue
If (vertices.Length - iLoc > 0) Then
vertices = vertices.Substring(iLoc + 1) 'sVertices.Length - iLoc)
Else
Exit For
End If
Else
Exit For
End If
Next
End If
End If
Else
' Retrieving ListPoint from geometry
Dim oPoly As ESRI.ArcGIS.Geometry.IPolyline = TryCast(inFeature.ShapeCopy, ESRI.ArcGIS.Geometry.IPolyline)
Dim colLink As ESRI.ArcGIS.Geometry.IPointCollection = TryCast(oPoly, ESRI.ArcGIS.Geometry.IPointCollection)
If (colLink IsNot Nothing AndAlso colLink.PointCount > 2) Then
Dim oPoint As ESRI.ArcGIS.Geometry.IPoint
xmlLink_Vertices = outDOMDoc.createElement("Vertices")
xmlLink.appendChild(xmlLink_Vertices)
For i As Integer = 1 To colLink.PointCount - 2
oPoint = colLink.Point(i)
xmlLink_Vertex = outDOMDoc.createElement("Vertex")
xmlLink_Vertices.appendChild(xmlLink_Vertex)
xmlLink_XVertex = outDOMDoc.createElement("X")
xmlLink_Vertex.appendChild(xmlLink_XVertex)
xmlLink_XVertex.nodeTypedValue = oPoint.X
xmlLink_YVertex = outDOMDoc.createElement("Y")
xmlLink_Vertex.appendChild(xmlLink_YVertex)
xmlLink_YVertex.nodeTypedValue = oPoint.Y
Next
End If
End If
'Specifying its properties
Select Case (inFeature.Class.AliasName)
Case "LV_Line"
CompleteXMLEltByProperties(inFeature, outDOMDoc, xmlLink, m_LVLinesPropertiesArray)
End Select
'-------- Feature Section END related to the "infeature" --------
End Sub
' The following CreateBasicXMLItmesForSchematicElt private procedure is used to create the first expected XML items for a XML NodeFeature or LinkFeature
Private Sub CreateBasicXMLItemsForSchematicElt(ByVal inFeature As ESRI.ArcGIS.Geodatabase.IFeature, ByRef outDOMDoc As MSXML2.DOMDocument, ByRef outXMLElement As MSXML2.IXMLDOMElement, ByVal inEltTypeName As String)
Dim xmlElt_EltTypeName As MSXML2.IXMLDOMElement
Dim xmlElt_ExternalUID As MSXML2.IXMLDOMElement
Dim xmlElt_DatasourceName As MSXML2.IXMLDOMElement
Dim xmlElt_UCID As MSXML2.IXMLDOMElement
Dim xmlElt_UOID As MSXML2.IXMLDOMElement
' Specifying its FeatureClassName
xmlElt_EltTypeName = outDOMDoc.createElement("FeatureClassName")
outXMLElement.appendChild(xmlElt_EltTypeName)
If (inFeature.Fields.FindField("Feeder") <> -1) Then
xmlElt_EltTypeName.nodeTypedValue = inEltTypeName & "sFeeder" & inFeature.Value(inFeature.Fields.FindField("Feeder")).ToString()
Else
xmlElt_EltTypeName.nodeTypedValue = inEltTypeName & "s"
End If
' Specifying its ExternalUniqueID
xmlElt_ExternalUID = outDOMDoc.createElement("ExternalUniqueID")
outXMLElement.appendChild(xmlElt_ExternalUID)
xmlElt_ExternalUID.nodeTypedValue = inEltTypeName & "-" & inFeature.OID.ToString()
' Specifying its DatasourceName
xmlElt_DatasourceName = outDOMDoc.createElement("DatasourceName")
outXMLElement.appendChild(xmlElt_DatasourceName)
xmlElt_DatasourceName.nodeTypedValue = "XMLDataSource"
' Specifying its UCID
xmlElt_UCID = outDOMDoc.createElement("UCID")
outXMLElement.appendChild(xmlElt_UCID)
xmlElt_UCID.nodeTypedValue = inFeature.Class.ObjectClassID
' Add UOID to NodeElement
xmlElt_UOID = outDOMDoc.createElement("UOID")
outXMLElement.appendChild(xmlElt_UOID)
xmlElt_UOID.nodeTypedValue = inFeature.OID
End Sub
' The following CompleteXMLEltByProperties private procedure is used to create all the expected propertyset properties listed in the input PropertiesArray array
Private Sub CompleteXMLEltByProperties(ByVal inFeature As ESRI.ArcGIS.Geodatabase.IFeature, ByRef outDOMDoc As MSXML2.DOMDocument, ByRef outXMLElement As MSXML2.IXMLDOMElement, ByVal propertiesArray() As String)
Dim i As Integer = 0
Dim xmlPropertySet As MSXML2.IXMLDOMElement
Dim xmlPropertyArray As MSXML2.IXMLDOMElement
Dim xmlPropertySetProperty As MSXML2.IXMLDOMElement
Dim xmlProperty_Key As MSXML2.IXMLDOMElement
Dim xmlProperty_Value As MSXML2.IXMLDOMElement
If (propertiesArray.Length > 0) Then
'-------- PropertySet Section START --------
' Creating the PropertySet element for the input outXMLElement
xmlPropertySet = outDOMDoc.createElement("PropertySet")
outXMLElement.appendChild(xmlPropertySet)
' Creating the PropertyArray element
xmlPropertyArray = outDOMDoc.createElement("PropertyArray")
xmlPropertySet.appendChild(xmlPropertyArray)
While (i < propertiesArray.Length)
' Creating the i PropertySetProperty
xmlPropertySetProperty = outDOMDoc.createElement("PropertySetProperty")
xmlPropertyArray.appendChild(xmlPropertySetProperty)
' Specifying the key && value field related to that i PropertySetProperty
xmlProperty_Key = outDOMDoc.createElement("Key")
xmlPropertySetProperty.appendChild(xmlProperty_Key)
xmlProperty_Key.nodeTypedValue = propertiesArray(i).ToString()
xmlProperty_Value = outDOMDoc.createElement("Value")
xmlPropertySetProperty.appendChild(xmlProperty_Value)
xmlProperty_Value.nodeTypedValue = inFeature.Value(inFeature.Fields.FindField(propertiesArray(i).ToString()))
i += 1
End While
End If
'-------- PropertySet Section END --------
End Sub
#End Region
End Class