【问题标题】:Serialize a FeatureClass to XML in ESRI ArcGIS在 ESRI ArcGIS 中将要素类序列化为 XML
【发布时间】:2011-02-15 14:44:00
【问题描述】:

如何将 IFeatureClass 对象序列化为 XML?

有一些资源可用于在其他 ArcObjects 上使用 IXMLSerializer,但这不适用于 IFeatureClass,因为它没有实现 ISerializable。

【问题讨论】:

    标签: arcgis esri arcobjects


    【解决方案1】:

    我实际上已经找到了我自己对这个问题的答案。我在这里发布这个问题和答案是为了他人的利益以及对我的方法的反馈/批评。

    IFeatureClass不能直接序列化,但是IRecordSet2可以。所以第一步是实现一个方法,将 IFeatureClass 转换为 IRecordSet2:

    private static IRecordSet2 ConvertToRecordset(IFeatureClass fc)
    {
        IRecordSet recSet = new RecordSetClass();
        IRecordSetInit recSetInit = recSet as IRecordSetInit;
        recSetInit.SetSourceTable(fc as ITable, null);
    
        return (IRecordSet2) recSetInit;
    }
    

    那么使用IXMLSerializer获取XML就很简单了:

    public static XElement StoreAsXml(IFeatureClass fc)
    {
        // Can't serialize a feature class directly, so convert
        //  to recordset first.
        IRecordSet2 recordset = ConvertToRecordset(fc);
    
        IXMLSerializer xmlSer = new XMLSerializerClass();
        string sXml = xmlSer.SaveToString(recordset, null, null);
    
        return XElement.Parse(sXml);           
    }
    

    但是,当您转换为 IRecordSet2 时,会丢失要素类名称,因此在写入文件时,我会在 XML 中添加一个元素来保存要素类名称:

    public static void StoreToFile(IFeatureClass fc, string filePath)
    {
        XElement xdoc = StoreAsXml(fc);
    
        XElement el = new XElement("FeatureClass", new XAttribute( "name", fc.AliasName ),
                                    xdoc);
    
        el.Save(filePath);
    }
    

    现在,只需反转将 XML 读入要素类的过程。请记住,添加了一个元素来存储要素类名称:

    public static IFeatureClass RetreiveFromFile(string filepath)
    {
        XElement xdoc = XElement.Load(filepath);
        string sName = xdoc.FirstAttribute.Value;
        XNode recordset = xdoc.FirstNode;
    
        return RetreiveFromXml(recordset, sName);
    }
    

    使用 IXMLSerializer 进行简单的反序列化以获得 IRecordSet2:

    public static IFeatureClass RetreiveFromXml(XNode node, string sName)
    {
        IXMLSerializer xmlDeSer = new XMLSerializerClass();
        IRecordSet2 recordset = (IRecordSet2)xmlDeSer.LoadFromString(node.ToString(), null, null);
    
        return ConvertToFeatureClass(recordset, sName);
    }
    

    这是棘手的部分。我愿意接受有关如何改进这一点的建议……将 IRecordSet2 对象转换为 IFeatureClass:

    private static IFeatureClass ConvertToFeatureClass(IRecordSet2 rs, string sName)
    {
        IWorkspaceFactory pWSFact = new ShapefileWorkspaceFactory();
    
        string sTempPath = Path.GetTempPath();
        IFeatureWorkspace pFWS = (IFeatureWorkspace)pWSFact.OpenFromFile( sTempPath, 0);
    
        // Will fail (COM E_FAIL) if the dataset already exists
        DeleteExistingDataset(pFWS, sName);
    
        IFeatureClass pFeatClass = null;
        pFeatClass = pFWS.CreateFeatureClass(sName, rs.Fields, null, null, esriFeatureType.esriFTSimple,
                                             "SHAPE", "");
    
        // Copy incoming record set table to new feature class's table
        ITable table = (ITable) pFeatClass;
        table = rs.Table;
    
        IFeatureClass result = table as IFeatureClass;
    
        // It will probably work OK without this, but it makes the XML match more closely
        IClassSchemaEdit3 schema = result as IClassSchemaEdit3;
        schema.AlterAliasName(sName);
        schema.AlterFieldAliasName("FID", "");
        schema.AlterFieldModelName("FID", "");
        schema.AlterFieldAliasName("Shape", "");
        schema.AlterFieldModelName("Shape", "");
    
        // If individual fields need to be edited, do something like this:
        //      int nFieldIndex = result.Fields.FindField("Shape");
        //      IFieldEdit2 field = (IFieldEdit2)result.Fields.get_Field(nFieldIndex);
    
        // Cleanup 
        DeleteExistingDataset(pFWS, sName);
    
        return table as IFeatureClass;
    }
    

    最后,一个用于删除现有数据集的实用方法。这是从某个地方复制/粘贴的,但我不记得出处了。

    public static void DeleteExistingDataset(IFeatureWorkspace pFWS, string sDatasetName)
    {
        IWorkspace pWS = (IWorkspace)pFWS;
        IEnumDatasetName pEDSN = pWS.get_DatasetNames(esriDatasetType.esriDTFeatureClass);
        bool bDatasetExists = false;
        pEDSN.Reset();
        IDatasetName pDSN = pEDSN.Next();
        while (pDSN != null)
        {
            if (pDSN.Name == sDatasetName)
            {
                bDatasetExists = true;
                break;
            }
            pDSN = pEDSN.Next();
        }
        if (bDatasetExists)
        {
            IFeatureClass pFC = pFWS.OpenFeatureClass(sDatasetName);
            IDataset pDataset = (IDataset)pFC;
            pDataset.Delete();
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-02-06
      • 1970-01-01
      • 2014-05-30
      • 2010-09-15
      • 1970-01-01
      • 2015-03-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多