2010-05-04 5 views
1

어떻게 IFeatureClass 객체를 XML로 직렬화 할 수 있습니까?ESRI에서 FeatureClass를 XML로 직렬화 ArcGIS

다른 ArcObjects에서 IXMLSerializer를 사용하기위한 리소스가 있지만 ISeializable을 구현하지 않아 IFeatureClass에서 작동하지 않습니다.

답변

7

나는이 질문에 대한 내 자신의 답변을 실제로 발견했습니다. 저는 다른 사람들의 이익을 위해이 질문과 답변을 게시하고 제 접근 방식에 대한 피드백/비평을하고 있습니다.

IFeatureClass는 직접 직렬화 할 수 없지만 IRecordSet2는 될 수 있습니다. 그래서 첫 번째 단계는 IRecordSet2에 IFeatureClass를 변환하는 방법을 구현한다 : 당신이 IRecordSet2로 변환 할 때

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);   
} 

그러나,이 기능을 잃게 :

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

    return (IRecordSet2) recSetInit; 
} 

를 그 다음은 XML 얻을 IXMLSerializer를 사용하기 쉽습니다 클래스 이름, 파일 쓰기, 내가 기능 클래스 이름을 유지하기 위해 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); 
} 

간단한 드 직렬화를 IRecordSet2를 얻을 수 IXMLSerializer를 사용하여 :

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); 
} 

가 까다로운 부분이었다. 나는 IFeatureClass에 IRecordSet2 객체를 은밀한 ...이를 개선하는 방법에 대한 제안에 열려있어 :

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(); 
    } 
}