diff --git a/PostalRegistry.sln.DotSettings b/PostalRegistry.sln.DotSettings index e98ba642..59c37cee 100644 --- a/PostalRegistry.sln.DotSettings +++ b/PostalRegistry.sln.DotSettings @@ -1,6 +1,7 @@  True <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb"><ExtraRule Prefix="" Suffix="" Style="aa_bb" /></Policy> + <Policy><Descriptor Staticness="Any" AccessRightKinds="Any" Description="Types and namespaces"><ElementKinds><Kind Name="NAMESPACE" /><Kind Name="CLASS" /><Kind Name="STRUCT" /><Kind Name="ENUM" /><Kind Name="DELEGATE" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb"><ExtraRule Prefix="" Suffix="" Style="aa_bb" /></Policy></Policy> <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> @@ -65,4 +66,5 @@ True True True + True diff --git a/src/PostalRegistry.Api.Oslo/Convertors/PostalInformationStatus.cs b/src/PostalRegistry.Api.Oslo/Convertors/PostalInformationStatus.cs new file mode 100644 index 00000000..60157775 --- /dev/null +++ b/src/PostalRegistry.Api.Oslo/Convertors/PostalInformationStatus.cs @@ -0,0 +1,20 @@ +namespace PostalRegistry.Api.Oslo.Convertors +{ + using Be.Vlaanderen.Basisregisters.GrAr.Legacy; + + public static class PostalInformationStatusExtensions + { + public static PostInfoStatus ConvertFromPostalInformationStatus(this PostalInformationStatus postalInformationStatus) + { + switch (postalInformationStatus) + { + case PostalInformationStatus.Retired: + return PostInfoStatus.Gehistoreerd; + + default: + case PostalInformationStatus.Current: + return PostInfoStatus.Gerealiseerd; + } + } + } +} diff --git a/src/PostalRegistry.Api.Oslo/Infrastructure/Options/AtomFeedConfigurationBuilder.cs b/src/PostalRegistry.Api.Oslo/Infrastructure/Options/AtomFeedConfigurationBuilder.cs new file mode 100644 index 00000000..0a097670 --- /dev/null +++ b/src/PostalRegistry.Api.Oslo/Infrastructure/Options/AtomFeedConfigurationBuilder.cs @@ -0,0 +1,37 @@ +namespace PostalRegistry.Api.Oslo.Infrastructure +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Reflection; + using Be.Vlaanderen.Basisregisters.Api.Syndication; + using Microsoft.Extensions.Configuration; + using Microsoft.SyndicationFeed; + using Microsoft.SyndicationFeed.Atom; + + public static class AtomFeedConfigurationBuilder + { + public static AtomFeedConfiguration CreateFrom(IConfigurationSection configuration, DateTimeOffset lastUpdated) + { + return new AtomFeedConfiguration( + configuration["Id"], + configuration["Title"], + configuration["Subtitle"], + configuration["GeneratorTitle"], + configuration["GeneratorUri"], + Assembly.GetEntryAssembly().GetName().Version.ToString(), + configuration["Rights"], + lastUpdated, + new SyndicationPerson(configuration["AuthorName"], configuration["AuthorEmail"], AtomContributorTypes.Author), + new SyndicationLink(new Uri(configuration["Self"]), AtomLinkTypes.Self), + new List(), + configuration + .GetSection("Related") + .GetChildren() + .Select(c => + new SyndicationLink(new Uri(c.Value), AtomLinkTypes.Related)) + .ToList() + ); + } + } +} diff --git a/src/PostalRegistry.Api.Oslo/PostalInformation/PostalInformationOsloController.cs b/src/PostalRegistry.Api.Oslo/PostalInformation/PostalInformationOsloController.cs index aba8ccec..d3be61b2 100644 --- a/src/PostalRegistry.Api.Oslo/PostalInformation/PostalInformationOsloController.cs +++ b/src/PostalRegistry.Api.Oslo/PostalInformation/PostalInformationOsloController.cs @@ -2,8 +2,11 @@ namespace PostalRegistry.Api.Oslo.PostalInformation { using System; using System.Linq; + using System.Net.Mime; + using System.Text; using System.Threading; using System.Threading.Tasks; + using System.Xml; using Asp.Versioning; using Be.Vlaanderen.Basisregisters.Api; using Be.Vlaanderen.Basisregisters.Api.Exceptions; @@ -11,16 +14,22 @@ namespace PostalRegistry.Api.Oslo.PostalInformation using Be.Vlaanderen.Basisregisters.Api.Search.Filtering; using Be.Vlaanderen.Basisregisters.Api.Search.Pagination; using Be.Vlaanderen.Basisregisters.Api.Search.Sorting; + using Be.Vlaanderen.Basisregisters.Api.Syndication; using Be.Vlaanderen.Basisregisters.GrAr.Common; + using Be.Vlaanderen.Basisregisters.GrAr.Common.Syndication; using Be.Vlaanderen.Basisregisters.GrAr.Legacy; using Be.Vlaanderen.Basisregisters.GrAr.Legacy.Gemeente; using Be.Vlaanderen.Basisregisters.GrAr.Legacy.PostInfo; using Convertors; + using Infrastructure; using Infrastructure.Options; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; + using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Options; + using Microsoft.SyndicationFeed; + using Microsoft.SyndicationFeed.Atom; using Nuts; using Projections.Legacy; using Projections.Syndication; @@ -196,6 +205,92 @@ public async Task Count( }); } + /// + /// Vraag een lijst met wijzigingen van postinfo op. + /// + /// + /// + /// + /// + /// + [HttpGet("sync")] + [Produces("text/xml")] + [ProducesResponseType(typeof(string), StatusCodes.Status200OK)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] + [SwaggerResponseExample(StatusCodes.Status200OK, typeof(PostalInformationSyndicationResponseExamples))] + [SwaggerResponseExample(StatusCodes.Status400BadRequest, typeof(BadRequestResponseExamples))] + [SwaggerResponseExample(StatusCodes.Status500InternalServerError, typeof(InternalServerErrorResponseExamples))] + public async Task Sync( + [FromServices] IConfiguration configuration, + [FromServices] LegacyContext context, + [FromServices] IOptions responseOptions, + CancellationToken cancellationToken = default) + { + var filtering = Request.ExtractFilteringRequest(); + var sorting = Request.ExtractSortingRequest(); + var pagination = Request.ExtractPaginationRequest(); + + var lastFeedUpdate = await context + .PostalInformationSyndication + .AsNoTracking() + .OrderByDescending(item => item.Position) + .Select(item => item.SyndicationItemCreatedAt) + .FirstOrDefaultAsync(cancellationToken); + + if (lastFeedUpdate == default) + lastFeedUpdate = new DateTimeOffset(2020, 1, 1, 0, 0, 0, TimeSpan.Zero); + + var pagedPostalInformationSet = + new PostalInformationSyndicationQuery( + context, + filtering.Filter?.Embed) + .Fetch(filtering, sorting, pagination); + + return new ContentResult + { + Content = await BuildAtomFeed(lastFeedUpdate, pagedPostalInformationSet, responseOptions, configuration), + ContentType = MediaTypeNames.Text.Xml, + StatusCode = StatusCodes.Status200OK + }; + } + + private static async Task BuildAtomFeed( + DateTimeOffset lastFeedUpdate, + PagedQueryable pagedPostalInfoItems, + IOptions responseOptions, + IConfiguration configuration) + { + var sw = new StringWriterWithEncoding(Encoding.UTF8); + + using (var xmlWriter = XmlWriter.Create(sw, new XmlWriterSettings { Async = true, Indent = true, Encoding = sw.Encoding })) + { + var formatter = new AtomFormatter(null, xmlWriter.Settings) { UseCDATA = true }; + var writer = new AtomFeedWriter(xmlWriter, null, formatter); + var syndicationConfiguration = configuration.GetSection("Syndication"); + var atomFeedConfig = AtomFeedConfigurationBuilder.CreateFrom(syndicationConfiguration, lastFeedUpdate); + + await writer.WriteDefaultMetadata(atomFeedConfig); + + var postalInfos = pagedPostalInfoItems.Items.ToList(); + + var nextFrom = postalInfos.Any() + ? postalInfos.Max(x => x.Position) + 1 + : (long?) null; + + var nextUri = BuildNextSyncUri(pagedPostalInfoItems.PaginationInfo.Limit, nextFrom, syndicationConfiguration["NextUri"]); + if (nextUri != null) + await writer.Write(new SyndicationLink(nextUri, GrArAtomLinkTypes.Next)); + + foreach (var postalInfo in postalInfos) + await writer.WritePostalInfo(responseOptions, formatter, syndicationConfiguration["Category"], postalInfo); + + xmlWriter.Flush(); + } + + return sw.ToString(); + } + private static Uri? BuildNextUri(PaginationInfo paginationInfo, int itemsInCollection, string nextUrlBase) { var offset = paginationInfo.Offset; @@ -206,6 +301,13 @@ public async Task Count( : null; } + private static Uri? BuildNextSyncUri(int limit, long? from, string nextUrlBase) + { + return from.HasValue + ? new Uri(string.Format(nextUrlBase, from.Value, limit)) + : null; + } + private async Task GetPostinfoDetailGemeente( SyndicationContext syndicationContext, string? nisCode, diff --git a/src/PostalRegistry.Api.Oslo/PostalInformation/Query/PostalInformationSyndicationQuery.cs b/src/PostalRegistry.Api.Oslo/PostalInformation/Query/PostalInformationSyndicationQuery.cs new file mode 100644 index 00000000..7d0de240 --- /dev/null +++ b/src/PostalRegistry.Api.Oslo/PostalInformation/Query/PostalInformationSyndicationQuery.cs @@ -0,0 +1,240 @@ +namespace PostalRegistry.Api.Oslo.PostalInformation.Query +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Linq.Expressions; + using Be.Vlaanderen.Basisregisters.Api.Search; + using Be.Vlaanderen.Basisregisters.Api.Search.Filtering; + using Be.Vlaanderen.Basisregisters.Api.Search.Sorting; + using Be.Vlaanderen.Basisregisters.GrAr.Provenance; + using Microsoft.EntityFrameworkCore; + using NodaTime; + using Projections.Legacy; + using Projections.Legacy.PostalInformationSyndication; + + public class PostalInformationSyndicationQueryResult + { + public bool ContainsEvent { get; } + public bool ContainsObject { get; } + + public string PostalCode { get; } + public long Position { get; } + public string ChangeType { get; } + + public Instant RecordCreatedAt { get; } + public Instant LastChangedOn { get; } + public PostalInformationStatus? Status { get; } + public IEnumerable PostalNames { get; } + public string MunicipalityNisCode { get; } + public Organisation? Organisation { get; } + public string Reason { get; } + public string EventDataAsXml { get; } + + public PostalInformationSyndicationQueryResult( + string postalCode, + long position, + string changeType, + Instant recordCreatedAt, + Instant lastChangedOn, + string municipalityNisCode, + Organisation? organisation, + string reason) + { + ContainsEvent = false; + ContainsObject = false; + + PostalCode = postalCode; + Position = position; + ChangeType = changeType; + RecordCreatedAt = recordCreatedAt; + LastChangedOn = lastChangedOn; + MunicipalityNisCode = municipalityNisCode; + Organisation = organisation; + Reason = reason; + } + + public PostalInformationSyndicationQueryResult( + string postalCode, + long position, + string changeType, + Instant recordCreatedAt, + Instant lastChangedOn, + string municipalityNisCode, + Organisation? organisation, + string reason, + string eventDataAsXml) + : this(postalCode, + position, + changeType, + recordCreatedAt, + lastChangedOn, + municipalityNisCode, + organisation, + reason) + { + ContainsEvent = true; + + EventDataAsXml = eventDataAsXml; + } + + public PostalInformationSyndicationQueryResult( + string postalCode, + long position, + string changeType, + Instant recordCreatedAt, + Instant lastChangedOn, + PostalInformationStatus? status, + IEnumerable postalNames, + string municipalityNisCode, + Organisation? organisation, + string reason) : + this( + postalCode, + position, + changeType, + recordCreatedAt, + lastChangedOn, + municipalityNisCode, + organisation, + reason) + { + ContainsObject = true; + + Status = status; + PostalNames = postalNames; + } + + public PostalInformationSyndicationQueryResult( + string postalCode, + long position, + string changeType, + Instant recordCreatedAt, + Instant lastChangedOn, + PostalInformationStatus? status, + IEnumerable postalNames, + string municipalityNisCode, + Organisation? organisation, + string reason, + string eventDataAsXml) + : this( + postalCode, + position, + changeType, + recordCreatedAt, + lastChangedOn, + status, + postalNames, + municipalityNisCode, + organisation, + reason) + { + ContainsEvent = true; + EventDataAsXml = eventDataAsXml; + } + } + + public class PostalInformationSyndicationQuery : Query + { + private readonly LegacyContext _context; + private readonly bool _embedEvent; + private readonly bool _embedObject; + + public PostalInformationSyndicationQuery(LegacyContext context, SyncEmbedValue embed) + { + _context = context; + _embedEvent = embed?.Event ?? false; + _embedObject = embed?.Object ?? false; + } + + protected override ISorting Sorting => new PostalInformationSyndicationSorting(); + + protected override Expression> Transformation + { + get + { + if (_embedEvent && _embedObject) + return syndicationItem => new PostalInformationSyndicationQueryResult( + syndicationItem.PostalCode, + syndicationItem.Position, + syndicationItem.ChangeType, + syndicationItem.RecordCreatedAt, + syndicationItem.LastChangedOn, + syndicationItem.Status, + syndicationItem.PostalNames, + syndicationItem.MunicipalityNisCode, + syndicationItem.Organisation, + syndicationItem.Reason, + syndicationItem.EventDataAsXml); + + if (_embedEvent) + return syndicationItem => new PostalInformationSyndicationQueryResult( + syndicationItem.PostalCode, + syndicationItem.Position, + syndicationItem.ChangeType, + syndicationItem.RecordCreatedAt, + syndicationItem.LastChangedOn, + syndicationItem.MunicipalityNisCode, + syndicationItem.Organisation, + syndicationItem.Reason, + syndicationItem.EventDataAsXml); + + if(_embedObject) + return syndicationItem => new PostalInformationSyndicationQueryResult( + syndicationItem.PostalCode, + syndicationItem.Position, + syndicationItem.ChangeType, + syndicationItem.RecordCreatedAt, + syndicationItem.LastChangedOn, + syndicationItem.Status, + syndicationItem.PostalNames, + syndicationItem.MunicipalityNisCode, + syndicationItem.Organisation, + syndicationItem.Reason); + + return syndicationItem => new PostalInformationSyndicationQueryResult( + syndicationItem.PostalCode, + syndicationItem.Position, + syndicationItem.ChangeType, + syndicationItem.RecordCreatedAt, + syndicationItem.LastChangedOn, + syndicationItem.MunicipalityNisCode, + syndicationItem.Organisation, + syndicationItem.Reason); + } + } + + protected override IQueryable Filter(FilteringHeader filtering) + { + var postalInformationSet = _context + .PostalInformationSyndication + .OrderBy(x => x.Position) + .AsNoTracking(); + + if (!filtering.ShouldFilter) + return postalInformationSet; + + if (filtering.Filter.Position.HasValue) + postalInformationSet = postalInformationSet.Where(item => item.Position >= filtering.Filter.Position); + + return postalInformationSet; + } + } + + internal class PostalInformationSyndicationSorting : ISorting + { + public IEnumerable SortableFields { get; } = new[] + { + nameof(PostalInformationSyndicationItem.Position) + }; + + public SortingHeader DefaultSortingHeader { get; } = new SortingHeader(nameof(PostalInformationSyndicationItem.Position), SortOrder.Ascending); + } + + public class PostalInformationSyndicationFilter + { + public long? Position { get; set; } + public SyncEmbedValue Embed { get; set; } + } +} diff --git a/src/PostalRegistry.Api.Oslo/PostalInformation/Responses/PostalInformationSyndicationResponse.cs b/src/PostalRegistry.Api.Oslo/PostalInformation/Responses/PostalInformationSyndicationResponse.cs new file mode 100644 index 00000000..005a66cd --- /dev/null +++ b/src/PostalRegistry.Api.Oslo/PostalInformation/Responses/PostalInformationSyndicationResponse.cs @@ -0,0 +1,240 @@ +namespace PostalRegistry.Api.Oslo.PostalInformation.Responses +{ + using System; + using System.Collections.Generic; + using System.Globalization; + using System.Linq; + using System.Runtime.Serialization; + using System.Threading.Tasks; + using System.Xml; + using Be.Vlaanderen.Basisregisters.GrAr.Common; + using Be.Vlaanderen.Basisregisters.GrAr.Common.Syndication; + using Be.Vlaanderen.Basisregisters.GrAr.Legacy; + using Be.Vlaanderen.Basisregisters.GrAr.Legacy.PostInfo; + using Be.Vlaanderen.Basisregisters.GrAr.Provenance; + using Convertors; + using Infrastructure.Options; + using Microsoft.Extensions.Options; + using Microsoft.SyndicationFeed; + using Microsoft.SyndicationFeed.Atom; + using Query; + using Swashbuckle.AspNetCore.Filters; + using Provenance = Be.Vlaanderen.Basisregisters.GrAr.Provenance.Syndication.Provenance; + + public static class PostalInformationSyndicationResponse + { + public static async Task WritePostalInfo( + this ISyndicationFeedWriter writer, + IOptions responseOptions, + AtomFormatter formatter, + string category, + PostalInformationSyndicationQueryResult postalInformation) + { + var item = new SyndicationItem + { + Id = postalInformation.Position.ToString(CultureInfo.InvariantCulture), + Title = $"{postalInformation.ChangeType}-{postalInformation.Position}", + Published = postalInformation.RecordCreatedAt.ToBelgianDateTimeOffset(), + LastUpdated = postalInformation.LastChangedOn.ToBelgianDateTimeOffset(), + Description = BuildDescription(postalInformation, responseOptions.Value.Naamruimte) + }; + + if (!string.IsNullOrWhiteSpace(postalInformation.PostalCode)) + { + item.AddLink( + new SyndicationLink( + new Uri($"{responseOptions.Value.Naamruimte}/{postalInformation.PostalCode}"), + AtomLinkTypes.Related)); + + //item.AddLink( + // new SyndicationLink( + // new Uri(string.Format(responseOptions.Value.DetailUrl, postalInformation.PostalCode)), + // AtomLinkTypes.Self)); + + //item.AddLink( + // new SyndicationLink( + // new Uri(string.Format($"{responseOptions.Value.DetailUrl}.xml", postalInformation.PostalCode)), + // AtomLinkTypes.Alternate) + // { MediaType = MediaTypeNames.Application.Xml }); + + //item.AddLink( + // new SyndicationLink( + // new Uri(string.Format($"{responseOptions.Value.DetailUrl}.json", postalInformation.PostalCode)), + // AtomLinkTypes.Alternate) + // { MediaType = MediaTypeNames.Application.Json }); + } + + item.AddCategory( + new SyndicationCategory(category)); + + item.AddContributor( + new SyndicationPerson( + postalInformation.Organisation == null ? Organisation.Unknown.ToName() : postalInformation.Organisation.Value.ToName(), + string.Empty, + AtomContributorTypes.Author)); + + await writer.Write(item); + } + + private static string BuildDescription(PostalInformationSyndicationQueryResult postalInformation, string naamruimte) + { + if (!postalInformation.ContainsEvent && !postalInformation.ContainsObject) + return "No data embedded"; + + var content = new SyndicationContent(); + if (postalInformation.ContainsObject) + content.Object = new PostalInfoSyndicationContent( + naamruimte, + postalInformation.PostalCode, + postalInformation.LastChangedOn.ToBelgianDateTimeOffset(), + postalInformation.Status, + postalInformation.PostalNames, + postalInformation.MunicipalityNisCode, + postalInformation.Organisation, + postalInformation.Reason); + + if (postalInformation.ContainsEvent) + { + var doc = new XmlDocument(); + doc.LoadXml(postalInformation.EventDataAsXml); + content.Event = doc.DocumentElement; + } + + return content.ToXml(); + } + } + + [DataContract(Name = "Content", Namespace = "")] + public class SyndicationContent : SyndicationContentBase + { + [DataMember(Name = "Event")] + public XmlElement Event { get; set; } + + [DataMember(Name = "Object")] + public PostalInfoSyndicationContent Object { get; set; } + } + + [DataContract(Name = "PostInfo", Namespace = "")] + public class PostalInfoSyndicationContent + { + /// + /// De technische id van de postinfo. + /// + [DataMember(Name = "Id", Order = 1)] + public string PostalCode { get; set; } + + /// + /// De identificator van de postcode. + /// + [DataMember(Name = "Identificator", Order = 1)] + public PostinfoIdentificator Identificator { get; set; } + + /// + /// De namen van het gebied dat de postcode beslaat, in de taal afkomstig uit het bPost bestand. + /// + [DataMember(Name = "Postnamen", Order = 2)] + public List PostalNames { get; set; } + + /// + /// De huidige fase in de doorlooptijd van de postcode. + /// + [DataMember(Name = "PostInfoStatus", Order = 3)] + public PostInfoStatus? Status { get; set; } + + /// + /// De NisCode van de gemeente waarmee de postcode verwant is. + /// + [DataMember(Name = "NisCode", Order = 3)] + public string MunicipalityNisCode { get; set; } + + /// + /// Creatie data ivm het item. + /// + [DataMember(Name = "Creatie", Order = 4)] + public Provenance Provenance { get; set; } + + public PostalInfoSyndicationContent( + string naamruimte, + string postcode, + DateTimeOffset version, + PostalInformationStatus? status, + IEnumerable postalNames, + string municipalityNisCode, + Organisation? organisation, + string reason) + { + PostalCode = postcode; + Identificator = new PostinfoIdentificator(naamruimte, postcode, version); + Status = status?.ConvertFromPostalInformationStatus(); + MunicipalityNisCode = municipalityNisCode; + PostalNames = postalNames? + .Select(name => new Postnaam(new GeografischeNaam(name.Name, name.Language.ConvertFromLanguage()))) + .ToList() + ?? new List(); + Provenance = new Provenance(version, organisation, new Reason(reason)); + } + } + + public class PostalInformationSyndicationResponseExamples : IExamplesProvider + { + const string RawXml = @" + + https://api.basisregisters.vlaanderen.be/v2/feeds/postinfo.atom + Basisregisters Vlaanderen - feed 'postinfo' + Deze Atom feed geeft leestoegang tot events op de resource 'postinfo'. + Basisregisters Vlaanderen + Gratis hergebruik volgens https://overheid.vlaanderen.be/sites/default/files/documenten/ict-egov/licenties/hergebruik/modellicentie_gratis_hergebruik_v1_0.html + 2020-09-17T09:14:41Z + + Digitaal Vlaanderen + digitaal.vlaanderen@vlaanderen.be + + + + + + + + 0 + PostalInformationWasRegistered-0 + 2019-11-21T09:34:51+01:00 + 2019-11-21T09:34:51+01:00 + + + bpost + + + + 89002019-11-21T08:34:51ZDePostCentrale bijhouding o.b.v. bPost-bestand + + 8900https://data.vlaanderen.be/id/postinfo/8900https://data.vlaanderen.be/id/postinfo89002019-11-21T09:34:51+01:002019-11-21T09:34:51+01:00bpostCentrale bijhouding o.b.v. bPost-bestand + ]]> + + + + 1 + PostalInformationBecameCurrent-1 + 2019-11-21T09:34:51+01:00 + 2019-11-21T09:34:51+01:00 + + + bpost + + + + 89002019-11-21T08:34:51ZDePostCentrale bijhouding o.b.v. bPost-bestand + + 8900https://data.vlaanderen.be/id/postinfo/8900https://data.vlaanderen.be/id/postinfo89002019-11-21T09:34:51+01:00Gerealiseerd2019-11-21T09:34:51+01:00bpostCentrale bijhouding o.b.v. bPost-bestand + ]]> + + +"; + + public XmlElement GetExamples() + { + var example = new XmlDocument(); + example.LoadXml(RawXml); + return example.DocumentElement; + } + } +} diff --git a/src/PostalRegistry.Api.Oslo/appsettings.json b/src/PostalRegistry.Api.Oslo/appsettings.json index 0e66447b..f8f8e41f 100644 --- a/src/PostalRegistry.Api.Oslo/appsettings.json +++ b/src/PostalRegistry.Api.Oslo/appsettings.json @@ -12,13 +12,30 @@ "http://localhost:5000" ], + "Syndication": { + "Category": "https://data.vlaanderen.be/ns/postinfo", + "Id": "https://legacy.staging-basisregisters.vlaanderen/v2/feeds/postinfo.atom", + "Title": "Basisregisters Vlaanderen - PostInfo register", + "Subtitle": "Deze Atom feed geeft leestoegang tot events op de resource 'postinfo'.", + "GeneratorTitle": "Basisregisters Vlaanderen", + "GeneratorUri": "", + "Rights": "Gratis hergebruik volgens https://overheid.vlaanderen.be/sites/default/files/documenten/ict-egov/licenties/hergebruik/modellicentie_gratis_hergebruik_v1_0.html", + "AuthorName": "Digitaal Vlaanderen", + "AuthorEmail": "digitaal.vlaanderen@vlaanderen.be", + "Self": "https://legacy.staging-basisregisters.vlaanderen/syndication/feed/postalinfo", + "NextUri": "https://legacy.staging-basisregisters.vlaanderen/v2/feeds/postinfo.atom?from={0}&limit={1}", + "Related": [ + "https://legacy.staging-basisregisters.vlaanderen" + ] + }, + "Naamruimte": "https://data.vlaanderen.be/id/postinfo", "DetailUrl": "https://basisregisters.vlaanderen.be/api/v2/postinfo/{0}", "VolgendeUrl": "https://basisregisters.vlaanderen.be/api/v2/postinfo?offset={0}&limit={1}", "ContextUrlList": "https://docs.basisregisters.dev-vlaanderen.be/context/postinfo/2022-01-11/postinfo_list.jsonld", "ContextUrlDetail": "https://docs.basisregisters.dev-vlaanderen.be/context/postinfo/2022-01-11/postinfo_detail.jsonld", "GemeenteNaamruimte": "https://data.vlaanderen.be/id/gemeente", - "GemeenteDetailUrl": "https://basisregisters.vlaanderen.be/api/v1/gemeenten/{0}", + "GemeenteDetailUrl": "https://basisregisters.vlaanderen.be/api/v2/gemeenten/{0}", "Serilog": { "MinimumLevel": {