Converting GeoJSON response to FeatureCollection - c#

Hi I am trying to parse the response from a OSM webservice into feature collection using GeoJson.Net
I am new to GeoJSON and not able to identify how to do so:
The Json response can be find here. The code I have written is:
System.IO.StreamReader file = new System.IO.StreamReader(filepath);
string content = file.ReadToEnd();
file.Close();
dynamic deserialized = JsonConvert.DeserializeObject(content);
List<Feature> lstGeoLocation = new List<Feature>();
foreach (JObject item in deserialized.features)
{
//var feature = new Feature();
var geom = item.Property("geometry").Value;
}
But this will be plain JSON parsing and there might be a better way to parse the same.
I also tried NetTopologySuite JSON extension but when i use following code it gives me exception
"Expected token 'type' not found."
System.IO.StreamReader file = new System.IO.StreamReader(filepath);
string content = file.ReadToEnd();
file.Close();
var reader = new NetTopologySuite.IO.GeoJsonReader();
var featureCollection = reader.Read <NetTopologySuite.Features.FeatureCollection>(content);

I hate to answer my I question but after two days of hit & trial I get it working with both NetTopology and GeoJson
// get the JSON file content
var josnData = File.ReadAllText(destinationFileName);
// create NetTopology JSON reader
var reader = new NetTopologySuite.IO.GeoJsonReader();
// pass geoJson's FeatureCollection to read all the features
var featureCollection = reader.Read<GeoJSON.Net.Feature.FeatureCollection>(josnData);
// if feature collection is null then return
if (featureCollection == null)
{
return;
}
// loop through all the parsed featurd
for (int featureIndex = 0;
featureIndex < featureCollection.Features.Count;
featureIndex++)
{
// get json feature
var jsonFeature = featureCollection.Features[featureIndex];
Geometry geom = null;
// get geometry type to create appropriate geometry
switch (jsonFeature.Geometry.Type)
{
case GeoJSONObjectType.Point:
break;
case GeoJSONObjectType.MultiPoint:
break;
case GeoJSONObjectType.LineString:
break;
case GeoJSONObjectType.MultiLineString:
break;
case GeoJSONObjectType.Polygon:
{
var polygon = jsonFeature.Geometry as GeoJSON.Net.Geometry.Polygon;
var coordinates = new List <Point3D>();
foreach (var ring in polygon.Coordinates)
{
if (ring.IsLinearRing())
{
foreach (var coordinate in ring.Coordinates)
{
var location = coordinate as GeographicPosition;
if (location == null)
{
continue;
}
coordinates.Add(new Point3D(location.Longitude,
location.Latitude,
location.Altitude.HasValue ? location.Altitude.Value : 0 ));
}
}
}
geom = new Polygon(new LinearRing(new CoordinateSequence(coordinates.ToArray())),
null);
}
break;
case GeoJSONObjectType.MultiPolygon:
break;
case GeoJSONObjectType.GeometryCollection:
break;
case GeoJSONObjectType.Feature:
break;
case GeoJSONObjectType.FeatureCollection:
break;
default:
throw new ArgumentOutOfRangeException();
}
}

//Steps to Converting GeoJSON response to FeatureCollection
//1. Add NetTopologySuite.IO.GeoJson package from Nuget Package Manager.
//2. Write Following Code Snap:
string Filepath = "Your filepath here";
var josnData = File.ReadAllText(Filepath);
var reader = new NetTopologySuite.IO.GeoJsonReader();
var featureCollection =
reader.Read<GeoJSON.Net.Feature.FeatureCollection>(josnData);
//in my case i did it like this
for (int fIndex = 0; fIndex < featureCollection.Features.Count; fIndex++)
{
var AreaDetails =
featureCollection.Features[fIndex].Properties;
for (int AIndex = 0; AIndex < AreaDetails.Count;
AIndex++)
{
var element = AreaDetails.ElementAt(AIndex);
var Key = element.Key;
var Value = element.Value;
if (Key == "GML_ID")
{
areaDetails.StateCode = Value.ToString();
}
else if (Key == "STNAME")
{
areaDetails.State = Value.ToString();
}
else if (Key == "DISTFULL")
{
areaDetails.DistrictCode = Value.ToString();
}
else if (Key == "DTNAME")
{
areaDetails.District = Value.ToString();
}
else if (Key == "IPCODE")
{
areaDetails.TalukaCode = Value.ToString();
}
else if (Key == "IPNAME")
{
areaDetails.Taluka = Value.ToString();
}
else if (Key == "VLGCD2001")
{
areaDetails.AreaCode = Value.ToString();
}
else if (Key == "VILLNAME")
{
areaDetails.AreaName = Value.ToString();
}
}
var AreaCoords = featureCollection.Features[fIndex].Geometry;
var Type = AreaCoords.Type;
LocationDetails locationDetails = new LocationDetails();
if (Type == GeoJSONObjectType.Polygon)
{
var polygon = AreaCoords as GeoJSON.Net.Geometry.Polygon;
var polygonCoords = polygon.Coordinates[0].Coordinates;
for (int AIndex = 0; AIndex < polygonCoords.Count; AIndex++)
{
locationDetails.lat = Convert.ToDecimal(polygonCoords[AIndex].Latitude);
locationDetails.lng = Convert.ToDecimal(polygonCoords[AIndex].Longitude);
locationDetailsList.Add(locationDetails);
}
}

Related

CADES signature with Json data in C#

I have below json data I need to apply CAdES-BES Signature with Automatic JSON Canonicalization. Please find my json data below. Helpful link from https://www.example-code.com/Csharp/itida_egypt_cades_bes_json_canonicalization.asp. I follow the steps but still digital signature is not applying. Its returns normal json data.
[HttpGet]
[Route("api/invoiceLines/")]
public IHttpActionResult getEInvoiceLines()
{
Chilkat.Crypt2 crypt = new Chilkat.Crypt2();
crypt.VerboseLogging = true;
Chilkat.Cert cert = new Chilkat.Cert();
cert.VerboseLogging = true;
// Set the smart card PIN, which will be needed for signing.
cert.SmartCardPin = "1245345";
// There are many ways to load the certificate.
// This example was created for a customer using an ePass2003 USB token.
// Assuming the USB token is the only source of a hardware-based private key..
bool success = cert.LoadFromSmartcard(#"E"); //Is this Right way To load certificate ?
Chilkat.JsonObject cmsOptions = new Chilkat.JsonObject();
// Setting "DigestData" causes OID 1.2.840.113549.1.7.5 (digestData) to be used.
cmsOptions.UpdateBool("DigestData", true);
cmsOptions.UpdateBool("OmitAlgorithmIdNull", true);
// Indicate that we are passing normal JSON and we want Chilkat do automatically
// do the ITIDA JSON canonicalization:
cmsOptions.UpdateBool("CanonicalizeITIDA", true);
crypt.CmsOptions = cmsOptions.Emit();
// The CadesEnabled property applies to all methods that create CMS/PKCS7 signatures.
// To create a CAdES-BES signature, set this property equal to true.
crypt.CadesEnabled = true;
crypt.HashAlgorithm = "sha256";
Chilkat.JsonObject jsonSigningAttrs = new Chilkat.JsonObject();
jsonSigningAttrs.UpdateInt("contentType", 1);
jsonSigningAttrs.UpdateInt("signingTime", 1);
jsonSigningAttrs.UpdateInt("messageDigest", 1);
jsonSigningAttrs.UpdateInt("signingCertificateV2", 1);
crypt.SigningAttributes = jsonSigningAttrs.Emit();
// By default, all the certs in the chain of authentication are included in the signature.
// If desired, we can choose to only include the signing certificate:
crypt.IncludeCertChain = false;
EInvoiceModel.Example ds = new EInvoiceModel.Example();
//Start issuer details
ds.issuer = new EInvoiceModel.Issuer();
ds.issuer.type = "B";
ds.issuer.id = "113317713";
ds.issuer.name = "Issuer Company";
//Start issuer address details
ds.issuer.address = new EInvoiceModel.Address();
ds.issuer.address.branchID = "1";
ds.issuer.address.country = "EG";
ds.issuer.address.governate = "Cairo";
ds.issuer.address.regionCity = "Nasr City";
ds.issuer.address.street = "stree1";
ds.issuer.address.buildingNumber = "Bldg. 0";
ds.issuer.address.postalCode = "68030";
ds.issuer.address.floor = "1";
ds.issuer.address.room = "123";
ds.issuer.address.landmark = "7660 Melody Trail";
ds.issuer.address.additionalInformation = "beside Town Hall";
//Start Receiver details
ds.receiver = new EInvoiceModel.Receiver();
ds.receiver.type = "B";
ds.receiver.id = "3125617";
ds.receiver.name = "Receiver company";
//Start Receiver address datails
ds.receiver.address = new EInvoiceModel.AddressReceiver();
ds.receiver.address.country = "EG";
ds.receiver.address.governate = "Cairo";
ds.receiver.address.regionCity = "Nasr City";
ds.receiver.address.street = "stree1";
ds.receiver.address.buildingNumber = "Bldg. 0";
ds.receiver.address.postalCode = "68030";
ds.receiver.address.floor = "1";
ds.receiver.address.room = "123";
ds.receiver.address.landmark = "7660 Melody Trail";
ds.receiver.address.additionalInformation = "beside Town Hall";
//Document type & version
ds.documentType = "i";
ds.documentTypeVersion = "1.0";
DateTime d = new DateTime();
ds.dateTimeIssued = d; //Invoice date
ds.taxpayerActivityCode = "9478"; //needed info
ds.internalID = "WADIn1234"; //Internal Invoice number
ds.salesOrderReference = "So1234"; //So number //optional
ds.salesOrderDescription = "SO1234"; //So additional Info //optional
ds.proformaInvoiceNumber = "SoPro123"; //optional
//Invoiceline Start
ds.invoiceLines = new List<EInvoiceModel.InvoiceLine>
{
new EInvoiceModel.InvoiceLine
{
description = "Computer1",
itemType = "GPC",
itemCode = "10001774",
unitType = "EA",
quantity = 2,
internalCode = "IC0",
salesTotal = 23.99,
total = 2969.89,
valueDifference = 7.00,
totalTaxableFees = 817.42,
netTotal = 880.71,
itemsDiscount = 5.00,
unitValue = new EInvoiceModel.UnitValue
{
currencySold = "EUR",
amountEGP = 189.40,
amountSold = 10.00,
currencyExchangeRate = 18.94,
},
discount = new EInvoiceModel.Discount
{
rate = 7,
amount = 66.29
},
taxableItems = new List<EInvoiceModel.TaxableItem>
{
new EInvoiceModel.TaxableItem
{
taxType = "T1",
amount = 272.07,
subType = "T1",
rate = 12
}
}
}
}; //Invoice Lines End
//Items total Discount and Sales/NetAmount
ds.totalDiscountAmount = 76.29;
ds.totalSalesAmount = 1609.90;
ds.netAmount = 1533.61;
//Tax Total Start
ds.taxTotals = new List<EInvoiceModel.TaxTotal>
{
new EInvoiceModel.TaxTotal
{
taxType = "T1",
amount = 477.54,
}
};//Tax Total End
//Total Sales Amount & discounts
ds.totalAmount = 5191.50;
ds.extraDiscountAmount = 5.00;
ds.totalItemsDiscountAmount = 14.00;
string strResultJson = JsonConvert.SerializeObject(ds);
//System.IO.File.WriteAllText(#"C:\inetpub\wwwroot\path.json", strResultJson);
// File.WriteAllText(#"ds.json", strResultJson);
// string jsonToSign = "{ ... }";
string jsonToSign = strResultJson;
// Create the CAdES-BES signature.
crypt.EncodingMode = "base64";
// Make sure we sign the utf-8 byte representation of the JSON string
crypt.Charset = "utf-8";
string sigBase64 = crypt.SignStringENC(jsonToSign);
// return Ok(ds);
return Ok(sigBase64);
}
public static string SerializeObject2(object obj, int indent = 0)
{
var sb = new StringBuilder();
if (obj != null)
{
string indentString = new string(' ', indent);
if (obj is string || obj.IsNumber())
{
sb.Append($"\"{obj}\"");
}
else if (obj.GetType().BaseType == typeof(Enum))
{
sb.Append($"\"{obj.ToString()}\"");
}
else if (obj is Array)
{
var elems = obj as IList;
sb.Append($"{indentString}- [{elems.Count}] :\n");
for (int i = 0; i < elems.Count; i++)
{
sb.Append(SerializeObject2(elems[i], indent + 4));
}
}
else
{
Type objType = (obj).GetType();
PropertyInfo[] props = objType.GetProperties();
foreach (PropertyInfo prop in props)
{
if (prop.GetIndexParameters().Length == 0)
{
object propValue = prop.GetValue(obj);
var elems = propValue as IList;
if (elems != null)
{
sb.Append($"\"{prop.Name.ToUpper()}\"");
foreach (var item in elems)
{
sb.Append($"\"{prop.Name.ToUpper()}\"");
sb.Append(SerializeObject2(item, indent + 4));
}
}
else
{
if (Assembly.GetExecutingAssembly().DefinedTypes.Select(p => p.Assembly).ToList().Contains(prop.PropertyType.Assembly))
{
sb.Append($"\"{prop.Name.ToUpper()}\"");
sb.Append(SerializeObject2(propValue, indent + 4));
}
else
{
sb.Append($"\"{prop.Name.ToUpper()}\"\"{propValue}\"");
}
}
}
else if (objType.GetProperty("Item") != null)
{
int count = -1;
if (objType.GetProperty("Count") != null &&
objType.GetProperty("Count").PropertyType == typeof(int))
{
count = (int)objType.GetProperty("Count").GetValue(obj, null);
}
for (int i = 0; i < count; i++)
{
object val = prop.GetValue(obj, new object[] { i });
sb.Append(SerializeObject2(val, indent + 4));
}
}
}
}
}
return sb.ToString();
}

Get string data Xpath

I need help to get data from the site. I use geckofx in my application. I want it to retrieve text data from the xpath location after loading the page
XPathResult xpathResult = geckoWebBrowser1.Document.EvaluateXPath("/html/body/table[3]/tbody/tr[1]/td[2]/a[1]");
IEnumerable<GeckoNode> foundNodes = xpathResult.GetNodes();
How to download data as text?
It looks like you are struggling to retrieve the text from the GeckoFX objects.
Here are a few calls and operations that should get you started:
//get by XPath
XPathResult xpathResult = _browser.Document.EvaluateXPath("//*[#id]/div/p[2]");
var foundNodes = xpathResult.GetNodes();
foreach (var node in foundNodes)
{
var x = node.TextContent; // get text text contained by this node (including children)
GeckoHtmlElement element = node as GeckoHtmlElement; //cast to access.. inner/outerHtml
string inner = element.InnerHtml;
string outer = element.OuterHtml;
//iterate child nodes
foreach (var child in node.ChildNodes)
{
}
}
//get by id
GeckoHtmlElement htmlElementById = _browser.Document.GetHtmlElementById("mw-content-text");
//get by tag
GeckoElementCollection byTag = _browser.Document.GetElementsByTagName("input");
foreach (var ele in byTag)
{
var y = ele.GetAttribute("value");
}
//get by class
var byClass = _browser.Document.GetElementsByClassName("input");
foreach (var node in byClass)
{
//...
}
//cast to a different object
var username = ((GeckoInputElement)_browser.Document.GetHtmlElementById("yourUsername")).Value;
//create new object from DomObject
var button = new GeckoButtonElement(_browser.Document.GetElementById("myBtn").DomObject);
public string extract(string xpath, string type)
{
string result = string.Empty;
GeckoHtmlElement elm = null;
GeckoWebBrowser wb = geckoWebBrowser1;//(GeckoWebBrowser)GetCurrentWB();
if (wb != null)
{
elm = GetElement(wb, xpath);
if (elm != null)
//UpdateUrlAbsolute(wb.Document, elm);
if (elm != null)
{
switch (type)
{
case "html":
result = elm.OuterHtml;
break;
case "text":
if (elm.GetType().Name == "GeckoTextAreaElement")
{
result = ((GeckoTextAreaElement)elm).Value;
}
else
{
result = elm.TextContent.Trim();
}
break;
case "value":
result = ((GeckoInputElement)elm).Value;
break;
default:
result = extractData(elm, type);
break;
}
}
}
return result;
}
private string extractData(GeckoHtmlElement ele, string attribute)
{
var result = string.Empty;
if (ele != null)
{
var tmp = ele.GetAttribute(attribute);
/*if (tmp == null)
{
tmp = extractData(ele.Parent, attribute);
}*/
if (tmp != null)
result = tmp.Trim();
}
return result;
}
private object GetCurrentWB()
{
if (tabControl1.SelectedTab != null)
{
if(tabControl1.SelectedTab.Controls.Count > 0)
//if (tabControl1.SelectedTab.Controls.Count > 0)
{
Control ctr = tabControl1.SelectedTab.Controls[0];
if (ctr != null)
{
return ctr as object;
}
}
}
return null;
}
private GeckoHtmlElement GetElement(GeckoWebBrowser wb, string xpath)
{
GeckoHtmlElement elm = null;
if (xpath.StartsWith("/"))
{
if (xpath.Contains("#class") || xpath.Contains("#data-type"))
{
var html = GetHtmlFromGeckoDocument(wb.Document);
HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
doc.LoadHtml(html);
var node = doc.DocumentNode.SelectSingleNode(xpath);
if (node != null)
{
var currentXpath = "/" + node.XPath;
elm = (GeckoHtmlElement)wb.Document.EvaluateXPath(currentXpath).GetNodes().FirstOrDefault();
}
}
else
{
elm = (GeckoHtmlElement)wb.Document.EvaluateXPath(xpath).GetNodes().FirstOrDefault();
}
}
else
{
elm = (GeckoHtmlElement)wb.Document.GetElementById(xpath);
}
return elm;
}
private string GetHtmlFromGeckoDocument(GeckoDocument doc)
{
var result = string.Empty;
GeckoHtmlElement element = null;
var geckoDomElement = doc.DocumentElement;
if (geckoDomElement is GeckoHtmlElement)
{
element = (GeckoHtmlElement)geckoDomElement;
result = element.InnerHtml;
}
return result;
}
private void button5_Click(object sender, EventArgs e)
{
var text = extract("/html/body/table[3]/tbody/tr[1]/td[2]/a[2]", "text");
MessageBox.Show(text);
}
I also insert the code from which I used a little longer code but it also works. maybe someone will need it. The creator of the code is Đinh Công Thắng, Web Automation App,
Regards

C# List embedded files inside a PDF file and get a file stream to one of the embedded files

I can create a PDF with embedded files using LaTeX for example:
\usepackage{embedfile}
\embedfile{abc.data}
\embedfile{def.data}
Using the Acrobat Reader I'm able to extract again the two data files.
But how can I do that from C#?
How can I list the files which are embedded inside a PDF, similiar to a directory list?
How can I get a file stream (readonly) to one of the embedded files inside a PDF?
Using the iTextSharp-LGPL PDF library I was able to solve it.
List embedded file names
public static string[] ListEmbeddedFileNames(string pdfFileName)
{
string[] fileNames = new string[0];
var reader = new iTextSharp.text.pdf.PdfReader(pdfFileName);
if (reader != null)
{
var root = reader.Catalog;
if (root != null)
{
var names = root.GetAsDict(iTextSharp.text.pdf.PdfName.NAMES);
if (names != null)
{
var embeddedFiles = names.GetAsDict(iTextSharp.text.pdf.PdfName.EMBEDDEDFILES);
if (embeddedFiles != null)
{
var namesArray = embeddedFiles.GetAsArray(iTextSharp.text.pdf.PdfName.NAMES);
if (namesArray != null)
{
int n = namesArray.Size / 2; // I don't understand why I have to divide by 2
fileNames = new string[n];
for (int i = 0; i < n; i++) fileNames[i] = namesArray[2 * i].ToString();
}
}
}
}
reader.Close();
}
return fileNames;
}
Get embedded file stream
public static Stream GetEmbeddedFileStream(string pdfFileName, string embeddedFileName)
{
byte[] data = GetEmbeddedFileData(pdfFileName, embeddedFileName);
if (data == null)
return null;
else
return new MemoryStream(data);
}
and
public static byte[] GetEmbeddedFileData(string pdfFileName, string embeddedFileName)
{
byte[] attachedFileBytes = null;
var reader = new iTextSharp.text.pdf.PdfReader(pdfFileName);
if (reader != null)
{
var root = reader.Catalog;
if (root != null)
{
var names = root.GetAsDict(iTextSharp.text.pdf.PdfName.NAMES);
if (names != null)
{
var embeddedFiles = names.GetAsDict(iTextSharp.text.pdf.PdfName.EMBEDDEDFILES);
if (embeddedFiles != null)
{
var namesArray = embeddedFiles.GetAsArray(iTextSharp.text.pdf.PdfName.NAMES);
if (namesArray != null)
{
int n = namesArray.Size;
for (int i = 0; i < n; i++)
{
i++;
var fileArray = namesArray.GetAsDict(i);
var file = fileArray.GetAsDict(iTextSharp.text.pdf.PdfName.EF);
foreach (iTextSharp.text.pdf.PdfName key in file.Keys)
{
string attachedFileName = fileArray.GetAsString(key).ToString();
if (attachedFileName == embeddedFileName)
{
var stream = (iTextSharp.text.pdf.PRStream)iTextSharp.text.pdf.PdfReader.GetPdfObject(file.GetAsIndirectObject(key));
attachedFileBytes = iTextSharp.text.pdf.PdfReader.GetStreamBytes(stream);
break;
}
}
if (attachedFileBytes != null) break;
}
}
}
}
}
reader.Close();
}
return attachedFileBytes;
}
I've checked my solution by computing MD5 checksums over the embedded files.

Is there a way to deserialize a specific property of a YAML document?

In JSON.Net I can read a JSON file into a data structure and then only convert the properties that I'm interested in to objects. For example, if I have a JSON file like
{
"Bob": {
"Steve": 5
}
}
I can get the object like so:
class SteveObject {
public int Steve;
}
var jsonSerializer = JsonSerializer.Create()
var jsonFile = JObject.Parse(text);
vat steveObject = jsonFile["Bob"].ToObject<SteveObject>(jsonSerializer)
How do I do the same thing with YAMLDotNet or SharpYaml? I.e. if I have a YAML file like
Bob:
Steve: 5
How do I reconstruct the SteveObject from that without having to create the outer object?
Ok, I've written some code using SharpYaml that takes a simplified JPath query and returns the requested object.
public static T ReadPath<T>(Serializer serializer, string yaml, string path) {
var eventReader = new EventReader(new Parser(new StringReader(yaml)));
var streamReader = new MemoryStream(Encoding.UTF8.GetBytes(path ?? ""));
if ((char)streamReader.ReadByte() != '$')
throw new Exception();
if (streamReader.Position == streamReader.Length)
return serializer.Deserialize<T>(eventReader);
eventReader.Expect<StreamStart>();
eventReader.Expect<DocumentStart>();
while (streamReader.Position < streamReader.Length) {
if ((char)streamReader.ReadByte() != '.')
throw new Exception();
eventReader.Expect<MappingStart>();
var currentDepth = eventReader.CurrentDepth;
var nextKey = ReadPropertyName(streamReader);
if (string.IsNullOrEmpty(nextKey))
throw new Exception();
while (eventReader.Peek<Scalar>() == null || eventReader.Peek<Scalar>().Value != nextKey) {
eventReader.Skip();
// We've left the current mapping without finding the key.
if (eventReader.CurrentDepth < currentDepth)
throw new Exception();
}
eventReader.Expect<Scalar>();
}
return serializer.Deserialize<T>(eventReader);
}
public static string ReadPropertyName(MemoryStream stream) {
var sb = new StringBuilder();
while (stream.Position < stream.Length) {
var nextChar = (char) stream.ReadByte();
if (nextChar == '.') {
stream.Position--;
return sb.ToString();
}
sb.Append(nextChar);
}
return sb.ToString();
}
Given the above YAML the following works:
var t = "Bob:\r\n Point: [1.0, 2.0, 3.0]\r\n Steve: 5\r\n";
var serializer = new Serializer(settings);
var s = ReadPath<SteveObject>(serializer, t, "$.Bob"); // { "Steve": 5 }
var s2 = ReadPath<int>(serializer, t, "$.Bob.Steve"); // 5
Sure wish there were a library for this, though.

Control validation against XmlSchemaSimpleTypeRestriction.Facets

I have a a desktop application with a System.Windows.Form containing some TextBox controls. I need to validate the control values against restrictions of an xml schema.
For each TextBox I can retrieve the relevant XmlSchemaSimpleTypeRestriction from its type and then use a method as follows to validate its value:
public static bool Validate(XmlSchemaSimpleTypeRestriction restriction, string value)
{
bool isENum = false;
bool isValidEnum = false;
foreach (var item in restriction.Facets)
{
XmlSchemaLengthFacet lengthFacet = item as XmlSchemaLengthFacet;
if (lengthFacet != null)
{
int length = Int32.Parse(lengthFacet.Value);
if (!(value.Length == length))
return false;
}
XmlSchemaMinLengthFacet minLenghtFacet = item as XmlSchemaMinLengthFacet;
if (minLenghtFacet != null)
{
int length = Int32.Parse(minLenghtFacet.Value);
if (!(value.Length >= length))
return false;
}
XmlSchemaMaxLengthFacet maxLenghtFacet = item as XmlSchemaMaxLengthFacet;
if (maxLenghtFacet != null)
{
int length = Int32.Parse(maxLenghtFacet.Value);
if (!(value.Length <= length))
return false;
}
XmlSchemaPatternFacet patternFacet = item as XmlSchemaPatternFacet;
if (patternFacet != null)
{
Regex re = new Regex(patternFacet.Value);
if (!re.IsMatch(value))
return false;
}
XmlSchemaEnumerationFacet enumFacet = item as XmlSchemaEnumerationFacet;
if (patternFacet != null)
{
isENum = true;
if (StringComparer.InvariantCultureIgnoreCase.Compare(value, enumFacet.Value) == 0)
isValidEnum = true;
}
if (isENum && (!isValidEnum))
return false;
return true;
}
I am going to use this method in the Validating event of the controls. Is there any simpler way of doing this?
Ok, it's a little more complicated than I initially thought. Basically, you need create an XmlSchema that expects a single element with the provided restriction. Then you create an XML element with the provided value and validate it against the schema using an XmlReader:
public static bool Validate(XmlSchemaSimpleTypeRestriction restriction, string value)
{
var schema = new XmlSchema();
schema.Items.Add(new XmlSchemaElement
{
Name = "value",
SchemaType = new XmlSchemaSimpleType { Content = restriction }
});
var schemaSet = new XmlSchemaSet();
schemaSet.Add(schema);
var readerSettings = new XmlReaderSettings
{
ValidationType = ValidationType.Schema,
ValidationFlags = XmlSchemaValidationFlags.ReportValidationWarnings,
Schemas = schemaSet
};
string xml = new XElement("value", value).ToString();
try
{
var reader = XmlReader.Create(new StringReader(xml), readerSettings);
while (reader.Read()) ;
return true;
}
catch (XmlSchemaValidationException)
{
return false;
}
}
I tested it with this code:
static void Main(string[] args)
{
var restriction = new XmlSchemaSimpleTypeRestriction { BaseTypeName = new XmlQualifiedName("string", "http://www.w3.org/2001/XMLSchema") };
restriction.Facets.Add(new XmlSchemaMinLengthFacet { Value = "3" });
Console.WriteLine(Validate(restriction, "str"));
}

Categories