Polygon in XSLT transformation - geography data type

The container definition was missing in model-root. It’s fixed now:

@washi This helped to transform the data in XSLT, but when I try to save it to database, I got error:

Could not add TestPolygon. Exception was encountered while updating data. For more information see Details.
-------------------------------- 
Could not add TestPolygon. Exception was encountered while updating data. For more information see Details.
-------------------------------- 
A .NET Framework error occurred during execution of user-defined routine or aggregate "geography": 
System.FormatException: 24142: Expected "(" at position 8. The input has "1".
System.FormatException: 
   at Microsoft.SqlServer.Types.WellKnownTextReader.RecognizeToken(Char token)
   at Microsoft.SqlServer.Types.WellKnownTextReader.ParseLineStringText()
   at Microsoft.SqlServer.Types.WellKnownTextReader.ParsePolygonText()
   at Microsoft.SqlServer.Types.WellKnownTextReader.ParseTaggedText(OpenGisType type)
   at Microsoft.SqlServer.Types.WellKnownTextReader.Read(OpenGisType type, Int32 srid)
   at Microsoft.SqlServer.Types.SqlGeography.ParseText(OpenGisType type, SqlChars taggedText, Int32 srid)
   at Microsoft.SqlServer.Types.SqlGeography.GeographyFromText(OpenGisType type, SqlChars taggedText, Int32 srid)
   at System.Data.Common.DbDataAdapter.UpdatedRowStatusErrors(RowUpdatedEventArgs rowUpdatedEvent, BatchCommandInfo[] batchCommands, Int32 commandCount)
   at System.Data.Common.DbDataAdapter.UpdatedRowStatus(RowUpdatedEventArgs rowUpdatedEvent, BatchCommandInfo[] batchCommands, Int32 commandCount)
   at System.Data.Common.DbDataAdapter.Update(DataRow[] dataRows, DataTableMapping tableMapping)
   at System.Data.Common.DbDataAdapter.UpdateFromDataTable(DataTable dataTable, DataTableMapping tableMapping)
   at System.Data.Common.DbDataAdapter.Update(DataTable dataTable)
   at Origam.DA.Service.AbstractSqlDataService.ExecuteUpdate(DataStructureQuery query, String transactionId, UserProfile profile, DataStructure dataStructure, IDbTransaction transaction, IDbConnection connection, List`1 deletedRowIds, DataTable changedTable, DataRowState rowState, DataStructureEntity entity, Int32 rowCount, Boolean forceBulkInsert)
   at Origam.DA.Service.AbstractSqlDataService.<>c__DisplayClass22_2.<UpdateData>b__1()
   at Origam.DA.Service.AbstractSqlDataService.UpdateData(DataStructureQuery query, IPrincipal userProfile, DataSet dataset, String transactionId, Boolean forceBulkInsert)

The XML data I’m trying to save, looks like this:

<ROOT>
  <TestPolygon TestGeography="POLYGON(14.428757007606 50.197251879067, 14.415778426264 50.196717768985, 14.415777618954 50.196725844024, 14.415779421294 50.196587139862, 14.415790963027 50.195698397276, 14.415816949028 50.193697527127, 14.415822142591 50.193297633847, 14.415836143327 50.193297980994, 14.424627734011 50.193659413604, 14.424648401463 50.193660072512, 14.425419720668 50.194162859587, 14.425994275757 50.194529358653, 14.426582853846 50.19489026733, 14.42700706928 50.195205163884, 14.427372254891 50.195498019248, 14.427482911079 50.195608412368, 14.427589240292 50.195714396531, 14.428008810211 50.196265621681, 14.428426101023 50.196865947851, 14.428650096847 50.197139289959, 14.428757007606 50.197251879067)" AreaHa="30.61" Selected="false" RecordCreated="2025-05-07T16:47:30.1211652+02:00" Id="05ca7505-8d1f-4e63-b40d-6ae728ae4bf2" RecordCreatedBy="3fb325e6-76ed-4a44-84ca-84e1597ef539">
  </TestPolygon>
</ROOT>

The attribute value TestGeography is result from function GE:PolygonFromJstk(). There is POLYGON(x1 x2,y1 y2,...), but SQL can save multiple polygon objects at once and expect double parentheses POLYGON((x1 x2,y1 y2,...)). See MS documentation:
https://learn.microsoft.com/en-us/sql/relational-databases/spatial/polygon?view=sql-server-ver16
When I add double parentheses to TestGeography attribute value manually, the data are saved to SQL database correctly.
So, you should probably modify the result from GE:PolygonFromJstk() function.

We will adjust the function so it returns the same left and right parts of the input (including the parenthenses).

Thank you! Could you please push it to the master, so I can test it?

@washi, @jsusen
Thank you. Now it is possible to save the polygon via workflow (LoadData → Transform → SaveData). But when I fill the polygon data to screen with geography field via UI action workflow, it is not possible to save the screen. There is an error:

2025-05-13 15:53:16,770 [26] ERROR Origam.DA.Service.AbstractSqlDataService - Update failed
System.Data.SqlClient.SqlException (0x80131904): A .NET Framework error occurred during execution of user-defined routine or aggregate "geography": 
System.FormatException: 24201: Latitude values must be between -90 and 90 degrees.
System.FormatException: 
   at Microsoft.SqlServer.Types.GeographyValidator.ValidatePoint(Double x, Double y, Nullable`1 z, Nullable`1 m)
   at Microsoft.SqlServer.Types.Validator.BeginFigure(Double x, Double y, Nullable`1 z, Nullable`1 m)
   at Microsoft.SqlServer.Types.ForwardingGeoDataSink.BeginFigure(Double x, Double y, Nullable`1 z, Nullable`1 m)
   at Microsoft.SqlServer.Types.CoordinateReversingGeoDataSink.BeginFigure(Double x, Double y, Nullable`1 z, Nullable`1 m)
   at Microsoft.SqlServer.Types.WellKnownTextReader.ParseLineStringText()
   at Microsoft.SqlServer.Types.WellKnownTextReader.ParsePolygonText()
   at Microsoft.SqlServer.Types.WellKnownTextReader.ParseTaggedText(OpenGisType type)
   at Microsoft.SqlServer.Types.WellKnownTextReader.Read(OpenGisType type, Int32 srid)
   at Microsoft.SqlServer.Types.SqlGeography.ParseText(OpenGisType type, SqlChars taggedText, Int32 srid)
   at Microsoft.SqlServer.Types.SqlGeography.GeographyFromText(OpenGisType type, SqlChars taggedText, Int32 srid)
.
The statement has been terminated.
   at System.Data.Common.DbDataAdapter.UpdatedRowStatusErrors(RowUpdatedEventArgs rowUpdatedEvent, BatchCommandInfo[] batchCommands, Int32 commandCount)
   at System.Data.Common.DbDataAdapter.UpdatedRowStatus(RowUpdatedEventArgs rowUpdatedEvent, BatchCommandInfo[] batchCommands, Int32 commandCount)
   at System.Data.Common.DbDataAdapter.Update(DataRow[] dataRows, DataTableMapping tableMapping)
   at System.Data.Common.DbDataAdapter.Update(DataTable dataTable)
   at Origam.DA.Service.AbstractSqlDataService.ExecuteUpdate(DataStructureQuery query, String transactionId, UserProfile profile, DataStructure dataStructure, IDbTransaction transaction, IDbConnection connection, List`1 deletedRowIds, DataTable changedTable, DataRowState rowState, DataStructureEntity entity, Int32 rowCount, Boolean forceBulkInsert) in D:\a\1\s\backend\Origam.DA.Service\AbstractSqlDataService.cs:line 950
   at Origam.DA.Service.AbstractSqlDataService.<>c__DisplayClass22_2.<UpdateData>b__1() in D:\a\1\s\backend\Origam.DA.Service\AbstractSqlDataService.cs:line 586
   at Origam.DA.Service.AbstractSqlDataService.UpdateData(DataStructureQuery query, IPrincipal userProfile, DataSet dataset, String transactionId, Boolean forceBulkInsert) in D:\a\1\s\backend\Origam.DA.Service\AbstractSqlDataService.cs:line 582
ClientConnectionId:12805fa6-4238-41d5-b0ba-5a633c6978aa
Error Number:6522,State:1,Class:16

The screen looks like this:

This error is generate because the function GE:PolygonFromJstk processes only the first part of the polygon. The polygon object can have multiple parts - POLYGON((object_1 coordinates), (object_2 coordinates), ..., (object_x coordinates)) as I wrote in one of my previous posts (accordingly with the definition in MS documentation). If I have the source Polygon object like this:

POLYGON ((-647197.814 -1046759.6677, -647191.627 -1046745.09, -647185.4289 -1046730.8263, -647176.1155 -1046709.0245, -647163.733 -1046680.132, -647156.4596 -1046662.9094, -647142.0927 -1046627.2699, -647286.6349 -1046588.6936, -647432.0501 -1046548.8473, -647718.6738 -1046469.7102, -647766.8546 -1046455.9783, -647764.3137 -1046483.3874, -647764.4804 -1046504.6263, -647766.8537 -1046552.0734, -647770.2404 -1046581.7068, -647771.5104 -1046597.2643, -647772.357 -1046618.5369, -647772.7354 -1046647.5016, -647773.582 -1046682.4266, -647248.2 -1046836.4, -647245.4224 -1046837.3286, -647229.759 -1046819.0194, -647212.2965 -1046797.7468, -647208.2916 -1046792.7671, -647203.1322 -1046786.179, -647204.8881 -1046774.5693, -647202.8941 -1046771.6533, -647201.5 -1046767.6, -647197.814 -1046759.6677), (-647307.6137 -1046707.9647, -647307.6137 -1046705.848, -647304.227 -1046706.483, -647304.5445 -1046708.8114, -647307.6137 -1046707.9647))

the function GE:PolygonFromJstk result is:

POLYGON ((15.754196881926 50.163671695214, 15.754258643787 50.163808433097, 15.754321081925 50.163942379711, 15.754414290689 50.164146943489, 15.754538372114 50.1644180811, 15.754610839842 50.164579589147, 15.754751292514 50.16491307461, 15.752678440362 50.165103178741, 15.750591328401 50.165303651374, 15.746476437892 50.165704019586, 15.74578401362 50.165775137201, 15.745864906583 50.165533173861, 15.745897909614 50.165343398803, 15.745943829698 50.164917309286, 15.745946042788 50.164649157913, 15.745954264548 50.164508921406, 15.745977874015 50.164318119159, 15.746020781077 50.164059150567, 15.746067092463 50.163746474922, 15.753624157715 50.162932932178, 15.753664300227 50.16292760706, 15.753851551843 50.163107770162, 15.754058883385 50.163316307261, 15.754106265883 50.163365035159, 15.754167020323 50.163429353321, 15.754123330547 50.163531119102, 15.754146196494 50.163559278259, 15.754158836183 50.163596949855, 15.754196881926 50.163671695214), (-647307.6137 -1046707.9647, -647307.6137 -1046705.848, -647304.227 -1046706.483, -647304.5445 -1046708.8114, -647307.6137 -1046707.9647))

The second object of the polygon is not converted ant it causes the SQL server exception in previous post.

Thanks for the feedback, we will improve the function.