C# Rotate Images From Url's Stored in XML File - c#

Im trying to monetize a free winform app, basically I want to have 10 images rotate every 5 min in a picture box. I dont want to hard code these into the app, but store the image url's on my server in a xml file.
this is the xml on my server
<?xml version="1.0" encoding="utf-8"?>
<Advertisements>
<Ad>
<ImageUrl1>http://example.com/example.jpg</ImageUrl1>
<url1>http://example.com</url1>
</Ad>
<Ad>
<ImageUrl2>http://example.com/example2.jpg</ImageUrl2>
<url2>http://example.com</url2>
</Ad>
</Advertisements>
Im stuck on how to rotate through each node and display the image for 5 min
Tried to find a decent example, but most are for ASP.net
This is the code in my app:
XmlTextReader reader = null;
try {
string xmlURL = "http://example.com/ads.xml";
reader = new XmlTextReader(xmlURL);
reader.MoveToContent();
string elementName = "";
if ((reader.NodeType == XmlNodeType.Element) &&
(reader.Name == "Advertisements")) {
while (reader.Read()) {
if (reader.NodeType == XmlNodeType.Element)
elementName = reader.Name;
else {
if ((reader.NodeType == XmlNodeType.Text) &&
(reader.HasValue)) {
switch (elementName)
{
case "ImageUrl1":
picturebox.ImageLocation=reader.Value);
break;
}
}
}
}
}
}
catch (Exception) {
}
finally {
if (reader != null) reader.Close();
}

Your current code uses the older XmlReader approach to parsing XML manually. This is usually complex and tricky to get right. If you are using .NET version 3.5 or higher, you can use LINQ to XML for a cleaner interface to working with XML.
The approach I would take to solving your problem is this:
On app start-up, load the list of Advertisements from the server and cache the result in a static variable
Shuffle the list once (after loading it), so you can just keep iterating over the list when picking a new Ad to show (no need to randomize)
Use a Timer instance to rotate the image every 5 minutes
Here is some sample C# code using LINQ to XML for loading your XML data:
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
namespace StackOverflowQ21588436
{
public class Example
{
private const string XML =
#"<?xml version=""1.0"" encoding=""utf-8""?>
<Advertisements>
<Ad>
<ImageUrl>http://example.com/example.jpg</ImageUrl>
<url>http://example.com</url>
</Ad>
<Ad>
<ImageUrl>http://example.com/example2.jpg</ImageUrl>
<url>http://example.com/2.html</url>
</Ad>
</Advertisements>";
public static IList<Advertisement> GetAdvertisements()
{
var xmlDocument = XDocument.Parse(XML); // or XDocument.Load(url)
var adXmlNodes = xmlDocument.Element("Advertisements").Elements("Ad");
var adList = adXmlNodes.Select(xmlNode => new Advertisement {
ImageUrl = xmlNode.Element("ImageUrl").Value,
Href = xmlNode.Element("url").Value
}).ToList();
return adList;
}
}
public class Advertisement
{
public string ImageUrl { get; set; }
public string Href { get; set; } // named 'Href' to show property names don't have to match XML
}
}

Related

LINQ XML Get value of element from multiple where statement

First question on SO, apologies if I mess some of this up. I'm new to c# and LINQ and have spent the past 2 days searching SO for a solution, none seem to be exactly what I'm after. So...
The xml file I'm querying is generated from a DICOM Structured Report file. I'm trying to get specific values of elements from this xml file. These elements correspond to specific measurements that were taken during an ultrasound examination. The entire xml file is 15k lines long so for simplicity I've edited it. I'll just show one example of what I'm trying to do but the process will be the same for all other elements I'm looking to get.
The element I want to get has to meet 3 criteria, in this case Tricuspid Valve, Peak Velocity and Regurgitant Flow but this changes depending on the measurement that was taken. Once those criteria are met I want to get the value of , which in this case is 2120.
The xml
<report type="Comprehensive SR">
<document>
<content>
<container flag="SEPARATE">
<container flag="SEPARATE">
<code>
<meaning>Tricuspid Valve</meaning>
</code>
<container flag="SEPARATE">
<num>
<concept>
<meaning>Peak Velocity</meaning>
</concept>
<code>
<meaning>Regurgitant Flow</meaning>
</code>
<value>2120</value>
<unit>
<value>mm/s</value>
</unit>
</num>
My code in c#
XDocument xmlSR = XDocument.Load("DICOMSRtest.xml");
var TRVmax = from c in xmlSR.Descendants("container")
where (string)c.Element("code").Element("meaning") == "Tricuspid Valve"
where (string)c.Element("concept").Element("meaning") == "Peak Velocity"
where (string)c.Element("code").Element("meaning") == "Regurgitant Flow"
select c.Element("container").Element("num").Element("value");
Console.Write("TRVmax: " + TRVmax);
When I run the code I get the following
TRVmax: System.Linq.Enumerable+WhereSelectEnumerableIterator`2[System.Xml.Linq.XElement,System.Xml.Linq.XElement]
Any help or direction to some documentation which I can read to solve this would be greatly appreciated.
Try following :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
XDocument doc = XDocument.Load("PurchaseOrder.xml");
List<XElement> xContainers = doc.Descendants("container").Where(x => x.Element("num") != null).ToList();
List<Container> containers = new List<Container>();
foreach (XElement xContainer in xContainers)
{
Container newContainer = new Container();
containers.Add(newContainer);
newContainer.code = (string)xContainer.Descendants("code").FirstOrDefault();
newContainer.concept = (string)xContainer.Descendants("concept").FirstOrDefault();
newContainer.value = (int)xContainer.Descendants("value").FirstOrDefault();
newContainer.unit = (string)xContainer.Descendants("unit").FirstOrDefault();
}
}
}
public class Container
{
public string code { get; set; }
public string concept { get; set; }
public int value { get; set; }
public string unit { get; set; }
}
}

How to make serialized data compact?

i wrote an application which is a custom console that allows execution of various commands. One of the commands allows serialization of data. The input data is a string, which is a list of comma separated values.
My question is - how to make the serialized data compact as much as possible?
The serialization format is not important for me.
Here is the command's code:
using CustomConsole.Common;
using System.IO;
using System.Xml.Serialization;
using System;
namespace Shell_Commander.Commands
{
public class SerializeCommand : ICommand
{
private string _serializeCommandName = "serialize";
public string Name { get { return this._serializeCommandName; } set { _serializeCommandName = value; } }
public string Execute(string parameters)
{
try
{
var splittedParameters = parameters.Split(" ");
var dataToSerialize = splittedParameters[0].Split(",");
var pathTofile = splittedParameters[1].Replace(#"\", #"\\");
XmlSerializer serializer = new XmlSerializer(dataToSerialize.GetType());
using (StreamWriter writer = new StreamWriter(pathTofile))
{
serializer.Serialize(writer, dataToSerialize);
var length = new FileInfo(pathTofile).Length;
Console.WriteLine($"Wrote file to: {pathTofile}");
return length.ToString();
}
}
catch (Exception e)
{
Console.WriteLine(e);
return "0";
}
}
}
}
The command accepts 2 parameters:
Data to serialize
File path (in order to save the serialized data).
Example - for the "1,2,4" input, the following file will be saved:
<?xml version="1.0" encoding="utf-8"?>
<ArrayOfString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<string>1</string>
<string>2</string>
<string>4</string>
</ArrayOfString>
EDIT:
I want my command to be able to serialize also complex objects in the future, so writing the string as is to the file is not a solution.
I want to use only standard serialization methods and formats.

How to get the xml data from c# and show it as list in html using jquery

I am getting xml data from web api controller in c#. I need to show this data as list in html view page. I tried various methods but none of them is working.
Here is the XML Data which i am getting from api. Suggest a way how it can be done.
Thanks in advance.
<ArrayOfIDValue xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/IFlicksAPI.Controllers">
<IDValue>
<ID>1</ID>
<Name>Shuba</Name>
</IDValue>
<IDValue>
<ID>2</ID>
<Name>Raji</Name>
</IDValue>
<IDValue>
<ID>3</ID>
<Name>Renu</Name>
</IDValue>
</ArrayOfIDValue>
This way you can parse the xml and iterate through all the items
success: function(xml) {
$(xml).find('IDValue').each(function(){
var id = $(this).find("ID").text();
var name = $(this).find("name").text();
$("#list").append("<option value='" + id + "'>" + name + "</option>")
});
}
ofcource you need to use jQuery ajax function with your web api url
You can create a class using xml.serialiation and serialize the xml data in to an object of that class,
then just fill the list as it must be done
example: the xml template class
using System.Xml.Serialization;
namespace App
{
[XmlRoot("GuiConfig")]
public class ConfigParameters
{
[XmlElement("field1")]
public string field1;
[XmlElement("field2")]
public string field2;
}
how to serialize
public static void GetXmlData()
{
config = new ConfigParameters(); //global scope var
try
{
if (File.Exists("C:/path/config.xml"))
{
String xmlDoc = XDocument.Load("C:/path/config.xml").ToString();
XmlSerializer serializer = new
XmlSerializer(typeof(ConfigParameters));
using (TextReader reader = new StringReader(xmlDoc))
{
mainForm.config =
(ConfigParameters)serializer.Deserialize(reader);
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
throw;
}
}

trying to delete xmlns namespaces of nodes

I've got some problems with xml messages and c#.
The problem is a root element with no namespaces and all the namespaces are in the nodes.
I've got a part of the script running to delete the namespaces so I can read all the xml messages that will be sent to the webserver.
The message that gives the problems:
<?xml version="1.0"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<GetOrderResponseRequest xmlns="http://www.edibulb.nl/XML/Order:2">
<Header>
<UserName xmlns="urn:ebl:edibulb:xml:data:draft:ReusableAggregateBusinessInformationEntity:2">FBT_000390</UserName>
<Password xmlns="urn:ebl:edibulb:xml:data:draft:ReusableAggregateBusinessInformationEntity:2">1FWcgwrx9</Password>
<MessageID xmlns="urn:ebl:edibulb:xml:data:draft:ReusableAggregateBusinessInformationEntity:2" schemeDataURI="8719604082016">8719604082016100376</MessageID>
<MessageDateTime xmlns="urn:ebl:edibulb:xml:data:draft:ReusableAggregateBusinessInformationEntity:2" format="304">20170523090413+02:00</MessageDateTime>
</Header>
<Body>
<AgentParty>
<PrimaryID xmlns="urn:ebl:edibulb:xml:data:draft:ReusableAggregateBusinessInformationEntity:2" schemeID="251" schemeAgencyName="EBC">8719604178115</PrimaryID>
</AgentParty>
<GetOrderResponseDetails>
<MutationDateTime xmlns="urn:ebl:edibulb:xml:data:draft:ReusableAggregateBusinessInformationEntity:2" format="304">20170510000000+02:00</MutationDateTime>
<BuyerParty xmlns="urn:ebl:edibulb:xml:data:draft:ReusableAggregateBusinessInformationEntity:2">
<PrimaryID xmlns="urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:3" schemeID="251" schemeAgencyName="EBC">8719604082016</PrimaryID>
</BuyerParty>
</GetOrderResponseDetails>
</Body>
</GetOrderResponseRequest>
</soap:Body>
</soap:Envelope>
And here is the part of the script to translate on the webservice
the code below works perfectly fine if there are prefixes involved.
but it wont work with the xml defined above.
Here is the class that I call from the webservice.
First I check in the xml string if there are any prefixes.
RemoveNamespace remove = new RemoveNamespace();
public string orderrequest(string xmldoc, string ivbglns, bool success)
{
if (success == true)
{
if (xmldoc.Contains(":UserName"))
{
string xdoc = remove.removeall(xmldoc);
docx = new XmlDocument();
docx.LoadXml(xdoc);
}
else if(xmldoc.Contains("<UserName xmlns"))
{
string xdoc = remove.removexlmns(xmldoc);
docx = new XmlDocument();
docx.LoadXml(xmldoc);
}
// rest of the code for the response
}
}
and below the RemoveNameSpace part:
public string removeall(string xdoc)
{
string docx = RemoveAllNamespaces(xdoc);
return docx;
}
public static string RemoveAllNamespaces(string xmldoc)
{
XElement documentwithoutns = XRemoveAllNamespaces(XElement.Parse(xmldoc));
return documentwithoutns.ToString();
}
private static XElement XRemoveAllNamespaces(XElement Xmldoc)
{
if (!Xmldoc.HasElements)
{
XElement element = new XElement(Xmldoc.Name.LocalName);
element.Value = Xmldoc.Value;
foreach (XAttribute attribute in Xmldoc.Attributes())
element.Add(attribute);
return element;
}
return new XElement(Xmldoc.Name.LocalName, Xmldoc.Elements().Select(el => XRemoveAllNamespaces(el)));
}
public string removexlmns(string xdoc)
{
string pattern = "\\s+xmlns\\s*(:\\w)?\\s*=\\s*\\\"(?<url>[^\\\"]*)\\\"";
MatchCollection matchcol = Regex.Matches(xdoc, pattern);
foreach (Match m in matchcol)
{
xdoc = xdoc.Replace(m.ToString(), "");
}
return xdoc;
}
The error it returns is: The Prefix "cannot be redefined from" to 'urn:ebl:edibulb:xml:data:draft:ReusableAggregateBusinessInformationEntity:2' within the same start element tag.
I'm in search for a solution for this. The xml from above is a message thats beyond my control.
with Kind regards
Stephan
I would very strongly suggest you use the namespaces in whatever XML processing you are doing after this. Stop trying to remove them!
If you must remove them, it's worth noting that XElement.Name is mutable. You can remove all the namespace declarations and set all the names to their local names.
var doc = XDocument.Parse(xml);
doc.Descendants()
.Attributes()
.Where(x => x.IsNamespaceDeclaration)
.Remove();
foreach (var element in doc.Descendants())
{
element.Name = element.Name.LocalName;
}
See this fiddle for a demo.

Object reference not set to an instance of an object

I get an object reference not set to an instance of an object error in this program. Beginner in selenium so wanted to try opening a browser through xmlreader. I have the xmlreader code and openurl(simply open a google page) in the local library. I want to call these methods in the [setup] and [test] by creating an instance. Any help appreciated.
namespace ClassLibrary1
{
[TestFixture]
public class Class1
{
IWebDriver driver = null;
LocalLib localLib;
[SetUp]
public void openBrowser()
{
localLib = new LocalLib(driver);
localLib.StartDriverUsingXMLReader();
}
[Test]
public void url()
{
localLib.openUrl();
}
}
public class LocalLib
{
private IWebDriver driver = null;
public LocalLib(IWebDriver _driver)
{
this.driver = _driver;
}
public IWebDriver StartDriverUsingXMLReader()
{
try
{
XmlReader reader = XmlReader.Create(#"C:\Users\XXXXX\Desktop\XML.xml");
while (reader.Read())
{
if ((reader.NodeType == XmlNodeType.Element) && (reader.Name == "settings"))
{
if (reader.HasAttributes)
{
string parentBrowser = reader.GetAttribute("browser");
if (parentBrowser.ToLower().Equals("Firefox".ToLower()))
{
driver = new FirefoxDriver();
}
else if (parentBrowser.ToLower().Equals("googlechrome".ToLower()))
{
driver = new ChromeDriver(#"C:\chromedriver2_win32_0.8");
}
else if (parentBrowser.ToLower().Equals("Iexplore".ToLower()))
{
driver = new InternetExplorerDriver(#"C:\IEDriverServer_x64_2.32.3");
}
}
}
} return driver;
}
catch (Exception e)
{
Console.WriteLine(e.Message);
Console.WriteLine(e.StackTrace);
throw;
}
}
public void openUrl()
{
driver.Navigate().GoToUrl("www.google.com");
}
}
}
Error:
Object reference not set to an instance of an object.
at ClassLibrary1.LocalLib.StartDriverUsingXMLReader() in C:\Users\XXXX\XML test project\Class1.cs:line 52
Line 52:
string parentBrowser = reader.GetAttribute("browser");
Xml file info
<?xml version="1.0" encoding="utf-8" ?>
<settings>
<!--browser info-->
<settings browser="firefox"/>
</settings>
Double check the contents of the XML file with a working example.
Try using this as the contents of the XML.
<?xml version="1.0" encoding="utf-8" ?>
<!--browser info-->
<settings browser="firefox"/>
If you want to add more information you shoud add more attributes to the settings node, like this:
<?xml version="1.0" encoding="utf-8" ?>
<settings browser="firefox" username="abcd#yahoo.com" password="abcd" implicitWait="3" explicitWait="3"/>
Here you have a settings node, with the browser, username, password, implicitWait and explicitWait attributes.
Then from the C# code you can then read each attribute in the same way that you a already reading the browser attribute:
string parentBrowser = reader.GetAttribute("browser");
string username = reader.GetAttribute("username");
string password = reader.GetAttribute("password");
string implicitWait = reader.GetAttribute("implicitWait");
string explicitWait = reader.GetAttribute("explicitWait");
Notice that the attributes will be read as strings and if you need them to be integers you will need to convert them with something like this:
int implicitWait = int.Parse(reader.GetAttribute("implicitWait"));
Confirm whether or not your XML file has a browser attribute. If it does not, or it's an empty string, GetAttribute will return null and you'll get a NullReferenceException on the next line when you attempt to call ToLower on parentBrowser. The other potential problem would be that reader is null but I think it would have thrown earlier on if that were the case.
By the way, NullReferenceExceptions are among the most common runtime errors in C# code. You should have a look at other similar questions because the problem is always the same, you have some reference type that you try to use the . operator on when it is null. Figuring out why it is null and preventing that or adding checks prior to using the . operator always solves the problem.

Categories

Resources