Add to an arraylist from different arraylist index - c#

I have two array lists one in which I read in values from an XML, and then I add a specific tag to a listbox. From the listbox I transfer over the tag to another listbox, but the problem I am having is when trying to get the values of the selected item in the listbox in array1 to move over to array2.
How can I do this and make sure all things saved in the current index of arraylist1 move to arraylist2?
//Initialisation
int moduleCount = 0;
bool isFull = false;
ArrayList chosen= new ArrayList();
ArrayList module = new ArrayList();
String name;
String code;
String info;
String semester;
String tSlot;
String lSlot;
String preReq;
string xmlDirectory = Directory.GetCurrentDirectory();
public Form1()
{
InitializeComponent();
createBox();
//List<Array> a=new List<Array>();
// Console.WriteLine(module.ToString());
// getXML();
}
private void createBox()
{
String workingDir = Directory.GetCurrentDirectory();
XmlTextReader textReader = new XmlTextReader(workingDir + #"\XML.xml");
textReader.Read();
XmlNodeType type;
while (textReader.Read())
{
textReader.MoveToElement();
type = textReader.NodeType;
if (type == XmlNodeType.Element)
{
if (textReader.Name == "Code")
{
textReader.Read();
code = textReader.Value;
Console.WriteLine(code);
}
if (textReader.Name == "Name")
{
textReader.Read();
name = textReader.Value;
//selectionBox.Items.Add(name);
Console.WriteLine(name);
}
if (textReader.Name == "Semester")
{
textReader.Read();
semester = textReader.Value;
Console.WriteLine(semester);
}
if (textReader.Name == "Prerequisite")
{
textReader.Read();
preReq = textReader.Value;
Console.WriteLine(code);
}
if (textReader.Name == "LectureSlot")
{
textReader.Read();
lSlot = textReader.Value;
Console.WriteLine(lSlot);
}
if (textReader.Name == "TutorialSlot")
{
textReader.Read();
tSlot = textReader.Value;
Console.WriteLine(tSlot);
}
if (textReader.Name == "Info")
{
textReader.Read();
info = textReader.Value;
Console.WriteLine(info);
module.Add(new Modules(code, name, semester, tSlot, lSlot, info, preReq));
}
}
//Console.WriteLine(module);
}
foreach (object o in module)
{
Modules m = (Modules)o;
//String hold = m.mName;
selectionBox.Items.Add(m.mName);
}
textReader.Close();
//button event handler to move from one listbox to the other
if (selectionBox.SelectedItem != null)
{
chosenBox.Items.Add(selectionBox.SelectedItem);
selectionBox.Items.Remove(selectionBox.SelectedItem);
chosen.Add(selectionBox.SelectedItem);
errorLabel.Text = "";
moduleCount++;
if (moduleCount >= 8)
{
isFull = true;
errorLabel.Text = "You have selected 8 Modules please fill the fields and submit";
selectionBox.Enabled = false;
}
}
else
{
errorLabel.Text = "Please select a module";
}
numberChosen.Text = String.Format(moduleCount.ToString());
//Write to XML
foreach (object o in chosen)
{
Modules m = (Modules)o;
if (m.mPreReq != "None")
{
MessageBox.Show("You must chose module " + m.mPreReq);
//errorLabel.Text = "You must chose module " + m.mPreReq;
errorLabel.Text = "There is a prereq course";
req = true;
}
}

Ok it seems like you need to relate m.mName that you add to selectionBox to the actual Module you added to the module ArrayList so that you can add the members of that module to the chosen ArrayList later on. Something like:
if (selectionBox.SelectedItem != null)
{
chosenBox.Items.Add(selectionBox.SelectedItem);
selectionBox.Items.Remove(selectionBox.SelectedItem);
foreach (Module m in module)
{
if (m.Name.Equals(selectionBox.SelectedItem)
{
chosen.Add(m.Info);
chosen.Add(m.Code);
...
break;
}
}
errorLabel.Text = "";
moduleCount++;
if (moduleCount >= 8)
{
isFull = true;
errorLabel.Text = "You have selected 8 Modules please fill the fields and submit";
selectionBox.Enabled = false;
}
else
{
errorLabel.Text = "Please select a module";
}
}
numberChosen.Text = String.Format(moduleCount.ToString());

Related

How to limit the amount of parameters for concatenatenation?

The idea of the program is to concatenate different parameters and put it all inside another parameter. How to let the end user decide if he wants to concatenate 2 or 3 parameters. Right now it is like if you don't put in 3 parameters it won't work. Nothing I came up with works.
namespace CombineParametersWinForm
{
public partial class Form1 : System.Windows.Forms.Form
{
//Class variable
Document revitDoc { get; set; }
public Form1(Document doc)
{
InitializeComponent();
this.revitDoc = doc;
//Create a list of the parameters you want your user to choose from
List<string> stringParameters = new List<string>
{
"Weight",
"Angle",
"Manufacturer"
};
//Add list to comboboxes on form
foreach (string parameterName in stringParameters)
{
comboBox1.Items.Insert(0, parameterName);
comboBox2.Items.Insert(0, parameterName);
comboBox3.Items.Insert(0, parameterName);
}
}
private void button1_Click(object sender, EventArgs e)
{
FilteredElementCollector collector = new FilteredElementCollector(revitDoc);
ElementCategoryFilter filter = new ElementCategoryFilter(BuiltInCategory.OST_PipeFitting);
//Applying Filter
IList<Element> ducts = collector.WherePasses(filter).WhereElementIsNotElementType().ToElements();
foreach (Element duct in ducts)
{
//Get Parameter values
string parameterValue1 = duct.LookupParameter(comboBox1.Text).AsValueString();
string parameterValue2 = duct.LookupParameter(comboBox2.Text).AsValueString();
string parameterValue3 = duct.LookupParameter(comboBox3.Text).AsValueString();
string newValue = parameterValue1 + "-" + parameterValue2 + "-" + parameterValue3;
//do not need .ToString() when setting parameter
using (Transaction t = new Transaction(revitDoc, "Set Parameter name"))
{
t.Start();
duct.LookupParameter("New").Set(newValue);
t.Commit();
}
Ideas. First is pretty long one.
string parameterValue1 = duct.LookupParameter(comboBox1.Text).AsValueString();
string parameterValue2 = duct.LookupParameter(comboBox2.Text).AsValueString();
string parameterValue3 = duct.LookupParameter(comboBox3.Text).AsValueString();
if (parameterValue1 != "" || parameterValue1 != null)
{
parameterValue1 = parameterValue11;
}
if (parameterValue2 != "" || parameterValue2 != null)
{
parameterValue1 = parameterValue22;
}
if (parameterValue3 != "" || parameterValue3 != null)
{
parameterValue3 = parameterValue33;
}
if (parameterValue1 == "" || parameterValue1 == null)
{
parameterValue11 = "";
}
if (parameterValue2 == "" || parameterValue2 == null)
{
parameterValue22 = "";
}
if (parameterValue3 == "" || parameterValue3 == null)
{
parameterValue33 = "";
}
string newValue = parameterValue1 + "-" + parameterValue2 + "-" + parameterValue3;
using (Transaction t = new Transaction(revitDoc, "Set Parameter name"))
{
t.Start();
duct.LookupParameter("New").Set(newValue);
t.Commit();
}
}
}
}
}
Second is a short one but still doesn't work
string parameterValue1 = duct.LookupParameter(comboBox1.Text).AsValueString();
string parameterValue2 = duct.LookupParameter(comboBox2.Text).AsValueString();
string parameterValue3 = duct.LookupParameter(comboBox3.Text).AsValueString();
List<string> listParam = new List<string> { parameterValue1, parameterValue2, parameterValue3 };
foreach (string s in listParam)
{
if (s != "" /*&& s != null*/)
{
List<string> listParamNotNull = new List<string> { s };
string newValue = String.Join(" ,", listParamNotNull);
using (Transaction t = new Transaction(revitDoc, "Set Parameter name"))
{
t.Start();
duct.LookupParameter("New").Set(newValue);
t.Commit();
}
You are creating three separate Lists and wanting to do something against all of them combined, but actually doing against each of them individually, overwriting as you go.
Please take a closer look at your nested logic.
Something like this is likely more appropriate:
using System;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
string parameterValue1 = "Value1";
string parameterValue2 = ""; // purposefully providing an empty value
string parameterValue3 = "Value3";
var listParamIn = new List<string> { parameterValue1, parameterValue2, parameterValue3 };
var listParamOut = new List<string>();
foreach (string s in listParamIn){
if (string.IsNullOrEmpty(s))
continue;
listParamOut.Add(s);
}
string newValue = String.Join(", ", listParamOut);
Console.WriteLine(newValue);
/* continue with your transaction
using (Transaction t = new Transaction(revitDoc, "Set Parameter name")){
t.Start();
duct.LookupParameter("New").Set(newValue);
t.Commit();
}
*/
}
}
Output:
Value1, Value3
See:
https://dotnetfiddle.net/mXdL5F

SAP.Middleware.Connector.RfcInvalidParameterException: Table line 0 out of range: table is empty

I have a C# console aplication that connects to a SAP server to get data from some of its tables.
Sometimes this error pops up when i try to copy a value from a field in a SAP table called "SOHEADER" to a string variable.
Here's the stack trace:
SAP.Middleware.Connector.RfcInvalidParameterException: Table line 0
out of range: table is empty en
SAP.Middleware.Connector.RfcTable.get_Item(Int32 lineIndex) en
ExportarPedidosSAP.Program.ControlFacturasRemitosNotasCreditos(RfcDestination
rfcDest, String& nroerror) en
C:\Users\USER\Source\repos\BSCPY\BSCPY\ExportarPedidosSAP\Program.cs:línea
1220 en ExportarPedidosSAP.Program.ConnSAPNotasCreditos() en
C:\Users\USER\Source\repos\BSCPY\BSCPY\ExportarPedidosSAP\Program.cs:línea
936
Here is the ControlFacturasRemitosNotasCreditos function:
static void ControlFacturasRemitosNotasCreditos(RfcDestination rfcDest, out string nroerror)
{
Console.WriteLine("** Controlando remitos... ");
nroerror = "";
using (SqlBriefcaseCropScience db = new SqlBriefcaseCropScience())
{
using (var transaction = new TransactionScope(TransactionScopeOption.Required,
new TransactionOptions { IsolationLevel = IsolationLevel.Snapshot }))
{
List<NotaCreditoCabecera> lstpedidos = new List<NotaCreditoCabecera>();
List<NotaCreditoItem> lstItemProducto = new List<NotaCreditoItem>();
IQueryable<NotaCreditoCabecera> ilstpedidos = null;
IQueryable<Compania> ilstcompanias = null;
List<NotaCreditoItem> lstprod = null;
NotaCreditoItem itProd = null;
int statuscode = 0;
decimal FKIMG = 0;
string ProdCode = "";
string statusdesc = "";
string status_doc = "";
string LEGALNUMBER = "";
string LEGALNUMBER_DEL = "";
bool savecabecera = false;
bool nolegalnumber = false;
bool itemfacturado = false;
bool pedidofacturado = false;
List<string> List_LEGALNUMBER_DEL = new List<string>();
List<string> List_LEGALNUMBER = new List<string>();
ilstcompanias = db.Compania;
DateTime unmes = Helpers.GetCurrentDateTime().AddMonths(1);
if (ilstcompanias != null)
{
foreach (Compania comp in ilstcompanias.ToList())
{
ilstpedidos = db.NotaCreditoCabecera.Where(c => c.CodigoCompania == comp.Codigo &&
(c.CodigoEstado == 5 || c.CodigoEstado == 11 && (DbFunctions.TruncateTime(c.FechaEstado) <= DbFunctions.TruncateTime(unmes))));
if (ilstpedidos != null)
{
lstpedidos = ilstpedidos.ToList<NotaCreditoCabecera>();
if (lstpedidos.Count() > 0)
{
RfcRepository rfcRep = rfcDest.Repository;
var funcionStatus = ConfigurationManager.AppSettings["SAP-RFC-Status"];
foreach (NotaCreditoCabecera cabecera in lstpedidos.ToList())
{
lstprod = db.NotaCreditoItem.Where(c => c.CodigoCompania == comp.Codigo && c.NroPedido == cabecera.NroPedido).ToList();
IRfcFunction functionStatus = rfcRep.CreateFunction(funcionStatus);
functionStatus.SetValue("SEL_ORDERSTATUS", "X");
functionStatus.SetValue("P_VKORG", cabecera.SalesOrg);
functionStatus.SetValue("P_BRIEFDOC", cabecera.NroPedido);
IRfcTable tableHstatus = functionStatus.GetTable(ConfigurationManager.AppSettings["SAP-TablaH-Status"]);
IRfcTable tableIstatus = functionStatus.GetTable(ConfigurationManager.AppSettings["SAP-TablaI-Status"]);
IRfcTable tablaEstatus = functionStatus.GetTable(ConfigurationManager.AppSettings["SAP-TablaE"]);
functionStatus.Invoke(rfcDest);
status_doc = Convert.ToString(tableHstatus[0].GetValue("GBSTK")).ToUpper();
itemfacturado = false;
pedidofacturado = false;
nolegalnumber = false;
if (tableIstatus.RowCount > 0)
{
for (int e = 0; e < tableIstatus.RowCount; e++)
{
if (Convert.ToString(tableIstatus[e].GetValue("NETWR")) != "")
{
ProdCode = Convert.ToString(tableIstatus[e].GetValue("MATERIAL"));
itProd = lstprod.FirstOrDefault(i => i.CodigoProducto == ProdCode);
if (itProd != null)
{
//Num Factura
LEGALNUMBER = Convert.ToString(tableIstatus[e].GetValue("LEGALNUMBER")).Trim();
if (!String.IsNullOrEmpty(LEGALNUMBER))
{
itemfacturado = true;
//Num Remito
LEGALNUMBER_DEL = Convert.ToString(tableIstatus[e].GetValue("LEGALNUMBER_DEL")).Trim();
//Cantidad
FKIMG = (decimal.TryParse(Convert.ToString(tableIstatus[e].GetValue("FKIMG")), out FKIMG) == true) ?
Convert.ToDecimal(Convert.ToString(tableIstatus[e].GetValue("FKIMG"))) : 0;
//Si algun item no esta completamente facturado se considera el pedido no facturado
if ((LEGALNUMBER != "" && LEGALNUMBER_DEL != "") && (itProd.CantidadDevolucion == Convert.ToDecimal(FKIMG)) && (nolegalnumber == false))
{
pedidofacturado = true;
}
else
{
pedidofacturado = false;
break;
}
}
else
{
nolegalnumber = true;
}
}
}
}
//statuscode = 0;
//if (itemfacturado == true)
//{
// if (pedidofacturado == true)
// {
// statuscode = 12;
// }
//}
//if (statuscode > 0)
//{
// statusdesc = repositorioAdm.CEstado(cabecera.IdTipoOrden, statuscode);
// int reslog = ALogAutorizacion(db, transaction, cabecera.CodigoCompania,
// cabecera.SalesOrg, cabecera.CodigoDivision,
// cabecera.IdTipoOrden, cabecera.TipoOrden,
// cabecera.NroPedido.ToString(),
// cabecera.CodigoEstado.ToString(), cabecera.Estado,
// statuscode.ToString(), statusdesc, "inter", "");
// cabecera.CodigoEstado = statuscode;
// cabecera.Estado = statusdesc;
// cabecera.FechaEstado = Helpers.GetCurrentDateTime();
// savecabecera = true;
//}
}
//Tabla de Error
if (tablaEstatus.RowCount > 0)
{
//Obtengo el Estado
statuscode = 9;
cabecera.CodigoEstado = statuscode;
statusdesc = repositorioAdm.CEstado(cabecera.IdTipoOrden, statuscode);
cabecera.Estado = statusdesc;
cabecera.FechaEstado = Helpers.GetCurrentDateTime();
savecabecera = true;
int reslog = ALogAutorizacion(db, transaction, cabecera.CodigoCompania,
cabecera.SalesOrg, cabecera.CodigoDivision,
cabecera.IdTipoOrden, cabecera.TipoOrden,
cabecera.NroPedido.ToString(),
cabecera.CodigoEstado.ToString(),
cabecera.Estado,
statuscode.ToString(),
statusdesc, "inter", "");
}
}
}
}
if (savecabecera)
{
db.Configuration.ValidateOnSaveEnabled = false;
db.SaveChanges();
}
transaction.Complete();
}
}
}
}
}
Line 1220 inside ControlFacturasRemitosNotasCreditos:
status_doc = Convert.ToString(tableHstatus[0].GetValue("GBSTK")).ToUpper();
Line 936 inside ConnSAPNotasCreditos that calls the ControlFacturasRemitosNotasCreditos function:
ControlFacturasRemitosNotasCreditos(rfcDest, out nroerror);
Can somebodoy tell me what could be the issue here? Could it be that the field comes empty from the SAP table and if i try to copy it somewhere the whole thing crashes? Is there a safe way to check if the field is null before trying to copy it?
in your line
status_doc = Convert.ToString(tableHstatus[0].GetValue("GBSTK")).ToUpper();
you are adressing the IRfcTable tableHstatus with index 0, which means you're trying to read the first entry from that table object. That only works if the table has entries. You should first check whether the table contains any rows and only then continue. After invoking the RFC function, check property RowCount of your IRfcTable.
functionStatus.Invoke(rfcDest);
if (tableHstatus.RowCount > 0) {
status_doc = Convert.ToString(tableHstatus[0].GetValue("GBSTK")).ToUpper();
}
there's a number of reasons why a RFC function might return an empty table. It could be standard behavior in some cases, or it could be because some query parameter was wrong and no data was found, or because an error occurred in the function. Standard SAP BAPIs usually return a status structure or table (often of type BAPIRETURN or BAPIRET2) that contains additional information about error codes, messages etc.

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

order the events within button_Click

I am trying to get events to occur one at a time within my button_Click, but for some reason everything seems to wait to run until everything is complete. For instance image changes don't occur until everything else has occured.
private void button1_Click(object sender, EventArgs e)
{
pictureBox1.Image = Properties.Resources.running;
iTunesAppClass itunes = new iTunesAppClass();
IITLibraryPlaylist mainLibrary = itunes.LibraryPlaylist;
IITTrackCollection ittracks = mainLibrary.Tracks;
List<string> files = new List<string>();
List<string> musicfiles = new List<string>();
List<string> badfiles = new List<string>();
List<string> songlist = new List<string>();
int state = ((int)itunes.PlayerState);
string statestring = null;
if (state < 1) { statestring = "Stopped"; };
if (state == 1) { statestring = "Playing"; };
if (state == 1)
{
do
{
label5.Text = ("Pausing iTunes to maintain file integrity");
itunes.Pause();
state = (int)itunes.PlayerState;
}
while (state == 1);
}
if (state < 1) { statestring = "Stopped"; };
if (state == 1) { statestring = "Playing"; };
if (state != 1)
{
label5.Text = "Itunes is " + statestring;
}
string[] extensions = { "*.mp3", "*.mp4", "*.m4a", "*.m4v", "*.m4p", "*.m4b", "*.flac" };
string filepath = label4.Text;
foreach (string extension in extensions)
{
this.pictureBox1.Image = Properties.Resources.running;
try
{
files.AddRange(Directory.GetFiles(filepath, extension, SearchOption.AllDirectories));
}
catch (UnauthorizedAccessException) { }
}
foreach (string file in files)
{
try { string taglibfile = TagLib.File.Create(file).Tag.Title; musicfiles.Add(file); Console.WriteLine(taglibfile); }
catch { badfiles.Add(file); }
}
XDocument baddoc = new XDocument
(new XElement("Corrupt",
badfiles.Select(badfile =>
new XElement("File", badfile))));
baddoc.Save(label4.Text + "\\badfiles.xml");
// foreach(string musicfile in musicfiles)
//{ String Title = (TagLib.File.Create(musicfile).Tag.Title); }
this.pictureBox1.Image = Properties.Resources.skinitunes;
}

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