Having trouble dealing with xml and to properly use it for my purpose. So i am creating a test method and one of the parameters is xml data and i am not sure how to pass it in.
Service
public IEnumerable<Submissions> CheckingOutForUserReview(string data)
{
var _submissions = DataContextManager.StoredProcs.CheckingOutForUserReview<SSubmissions>(data, s => new Submissions
{
QRCodeGUID = SubmissionsColumnMap.QRCodeGUID(s),
StoragePath = SubmissionsColumnMap.StoragePath(s),
UploadedByUsersID = SubmissionsColumnMap.UploadedByUsersID(s)
});
return _submissions;
}
Stored Proc:
public virtual IEnumerable<T> CheckingOutForUserReview<T>(string data, Func<IDataRecord, T> modelBinder)
{
SqlCommand _command = new SqlCommand("dbo.CheckingOutForUserReview");
_command.CommandType = CommandType.StoredProcedure;
_command.Parameters.Add(new SqlParameter { ParameterName = "Data", SqlDbType = SqlDbType.Xml, Value = data });
return DbInstance.ExecuteAs<T>(_command, modelBinder);
}
This is my TestMethod:
public void CheckingOutForUserReview()
{
string _data = #"<CheckingOutForUserReview xmlns:i=""www.w3.org/2001/XMLSchema-instance"" xmlns=""schemas.name.com/2013/03/Malt.Models"">
<Record>
<QRCodeID>2FAC636E-F96C-4465-9272-760BAF73C0DF</QRCodeID>
<SubmissionID>10B5236C-47FD-468D-B88D-D789CA0C663A</SubmissionID>
<UserID>1</UserID>
<Page>1</Page>
</Record>
</CheckingOutForUserReview>";
XmlDocument doc = new XmlDocument();
doc.LoadXml(_data);
var _Svc = new SubmissionsService();
var _checkins = _Svc.CheckingOutForUserReview(doc.InnerXml);
}
UPDATE:
my CheckingOutForUserReview() method accepts a XmlDocument as i changed it to that in my stored procedure and with what i currently have it is giving an error that i have invalid arguments(System.Xml.XmlDocument) not sure if i messed up somewhere.
If this is a different way i am also open in trying new ways. Thanks for the help.
As I see there are two ways:
You should save your xml into an xml file by adding xml file in your
project then use it with XmlDocument using Load method like:
XmlDocument doc = new XmlDocument.Load(FileName);
...
...
var _checkins = _Svc.CheckingOutForUserReview(doc.innerXml);
Save your xml as a string literal and use it with XmlDocument using
LoadXml method like:
XmlDocument doc = new XmlDocument.LoadXml(stringThatContainsXml);
...
...
var _checkins = _Svc.CheckingOutForUserReview(doc.innerXml);
You can use XDocument and XElement classes as well but my focus on XmlDocument is that it will work for framework less than 3.5 too since XDocument and XElement is introduced in framework 3.5.
Also loading xml into a parser will help to filter out the invalid xml. (if mistakenly tried to use)
Another thing i have noticed in your snippet:
Assert.IsNotNull(_data);
It should come before the initialization of _Svc, because if there is no data in _data initialization doesn't make sense.
So your code looks like:
public void CheckingOutForUserReview()
{
string _data = "I want to pass in xml here";
Assert.IsNotNull(_data); <--------------- See the re-ordering
var _Svc = new SubmissionsService();
var _checkins = _Svc.CheckingOutForUserReview(_data);
}
Like I said in a comment, I think the best way to do this is to save the XML into a separate file.
If you don't want to do that, you can use verbatim string literal (note the double quotes):
string data = #"<CheckingOutForUserReview xmlns:i=""www.w3.org/2001/XMLSchema-instance"" xmlns=""schemas.name.com/2013/03/Malt.Models"">
<Record>
<QRCodeID>2FAC636E-F96C-4465-9272-760BAF73C0DF</QRCodeID>
<SubmissionID>10B5236C-47FD-468D-B88D-D789CA0C663A</SubmissionID>
<UserID>1</UserID>
<Page>1</Page>
</Record>
</CheckingOutForUserReview>";
I don't see what is the problem in passing any kind of strings as a parameter into a method
If your XML is generated from your code, you better have used a StringBuilder to build it to reduce creating new references while concatenating your string.
If your XML is originally from a file, pass the file path into your method, and open the document there. there are a lot of different ways to open and read XML documents, or loading a string to an XML document and deal with it as XML rather than a string.
Examples:
http://www.codeproject.com/Articles/24375/Working-with-XML
http://forum.codecall.net/topic/58239-c-tutorial-reading-and-writing-xml-files/
and finally from MSDN:
http://msdn.microsoft.com/en-us/library/aa288481%28v=vs.71%29.aspx
enjoy
Related
I have and datable and a column of string data type in that column i put content of type ddl some like
create table
create view
create stored procedure
dt.columns("content") = "create procedure ...etc"
that work ok,
the problem is when i need recovery the content like xml. Now i do that with
Dim xmlcontent = dt.DataSet.GetXml().ToString()
that return a xml like
<NewDataSet>
<Application_table>
<ID>PV</ID>
<NAme>dbo.uvw_Sample</Nombre>
<Content>/*
Run this script on SQL Server 2008 or later. There may be flaws if running on earlier versions of SQL Server.
*/
Create View...
...
</Content>
</Application_table>
</NewDataSet>
the exception is
XML parsing: line 5349, character 59, illegal xml character
i think the content in column content should for example change "<" for "<" or better specifiy the content like cdata
So I want to specify that the serialization of the column be as CDATA. Anyone know if there is way to do it?
You can try converting the nodes in question to a cdata node. This code might be obsolete as its very old, but it still works. I made an xml document from the dataset. Changed all the text nodes to CDATA nodes. Here is the code:
workingds = DataSetWithData
'Convert dataset to xmldatadocument
Dim myxmldoc As Xml.XmlDataDocument = New Xml.XmlDataDocument(workingds)
txtnodes = myxmldoc.GetElementsByTagName(strTextField)
For i = 0 To txtnodes.Count - 1
Me.makecdata(txtnodes(i))
Next i
'this subroutine takes the text node and wraps a cdata tag around it
'and returns it to the document
Public Sub makecdata(ByVal mynode As Xml.XmlNode)
Dim mcnode As Xml.XmlCDataSection, strtemp As String
strtemp = mynode.InnerText
mcnode = (mynode.OwnerDocument.CreateCDataSection(strtemp))
mynode.InnerXml = ""
mynode.AppendChild(mcnode)
mcnode = Nothing
End Sub
Use serialization:
private string DataSetToXml(DataSet ds)
{
using (var ms= new MemoryStream())
{
using (TextWriter sw= new StreamWriter(ms))
{
var xmlSerializer = new XmlSerializer(typeof(DataSet));
xmlSerializer.Serialize(sw, ds);
return Encoding.UTF8.GetString(memoryStream.ToArray());
}
}
}
or you can use .getXml() returned xml se how you can serialize into string Using StringWriter for XML Serialization
I'm trying to modify an attribute of an XML string using Json in C#. Currently I'm doing the following:
XmlDocument serializedFormXml = new XmlDocument();
serializedFormXml.LoadXml(mySerializedForm);
string formJsonString = JsonConvert.SerializeXmlNode(serializedFormXml, Newtonsoft.Json.Formatting.None, true);
JObject formJsonObj = JObject.Parse(formJsonString);
formJsonObj["#code"] = "myNewValue";
var xml = JsonConvert.DeserializeXmlNode(formJsonObj.ToString()).ToString();
When I do this I get get an exception on the last line:
Unable to cast object of type 'Newtonsoft.Json.Converters.XmlDocumentWrapper' to type 'Newtonsoft.Json.Converters.IXmlElement'
Any ideas what I'm doing wrong and how I can fix modify my form attribute "code"?
This is the XML I'm using:
<Form code="XYZ">
<Info>Data</Info>
.....
Thanks!
That's going to be way, way easier with Linq-to-XML:
var doc = XDocument.Parse(mySerializedForm);
doc.Root.SetAttributeValue(doc.Root.Name.Namespace + "code", "myNewValue");
var xml = doc.ToString();
This drops the XML declaration. If you need the XML declaration included, you can use the following extension method:
public static class XObjectExtensions
{
public static string ToXml(this XDocument xDoc)
{
using (var writer = new StringWriter())
{
xDoc.Save(writer);
return writer.ToString();
}
}
}
And then write:
var xml = doc.ToXml();
If specifically you need to make the encoding string say "UTF-8", use Utf8StringWriter from this answer.
Update
The reason you code fails is that you stripped the XML root element name away when you converted to json by passing true here:
string formJsonString = JsonConvert.SerializeXmlNode(serializedFormXml, Newtonsoft.Json.Formatting.None, true);
Thus you need to add it back when converting back:
var xml = JsonConvert.DeserializeXmlNode(formJsonObj.ToString(), serializedFormXml.DocumentElement.Name).ToString();
I am trying to store XPath of an XML attribute as a string in a separate file so that if XPath changes, I can easily modify the navigation to the attribute without changing code.
For example, in following XML:
<Result>
<Server = "main">
<Client id="1"></Client>
</Server>
</Result>
if I want to navigate to id attribute of Client element, I can have following string:
Result->Server->Client->id
I am not sure how in C# I can navigate using this string form of XPath and then, read the attribute value from the target XML.
Please help.
Harit
Well, firstly, your XML is a bit strange, with
<Server = "main">
Do you mean
<Server id="main">
But, regardless of that, you could just store the XPath directly instead of your string version. Like:
/Result/Server/Client[0]/#id
then you read the string from the file and pass it into something like:
public string GetClientIdString(string xPathString)
{
var doc = new XmlDocument();
doc.Load("SomeXml.xml");
return doc.DocumentElement.SelectSingleNode(xPathString).Value;
}
The issue becomes that you can't really store the XPath exactly how you would like if you plan on having more than one Client under Server. If you need that functionality, though, you could parse out your version of the XPath and do something like:
public IEnumerable<string> GetClientIdStrings(string elementXPath, string attribute)
{
var doc = new XmlDocument();
doc.Load(SomeXml.xml);
var clientIdStrings = new List<string>();
foreach(var node in doc.DocumentElement.SelectNodes(elementXPath))
{
clientIdStrings.Add(node.Attributes[attribute].Value);
}
return clientIdStrings;
}
I want to grab one specific value within an XML document at a url, I have managed to get a list of all values, but I'm not sure how to choose the specific value. The XML document is as follows;
<evec_api version="2.0" method="marketstat_xml">
<marketstat>
<type id="37">
<buy>
<volume>291092912</volume>
<avg>137.11</avg>
<max>156.06</max>
<min>53.46</min>
<stddev>31.00</stddev>
<median>140.28</median>
<percentile>156.05</percentile>
</buy>
<sell>
<volume>273042044</volume>
<avg>177.43</avg>
<max>339.00</max>
<min>166.22</min>
<stddev>30.83</stddev>
<median>170.38</median>
<percentile>166.26</percentile>
</sell>
<all>
<volume>574134956</volume>
<avg>154.64</avg>
<max>339.00</max>
<min>43.00</min>
<stddev>42.21</stddev>
<median>156.05</median>
<percentile>69.98</percentile>
</all>
</type>
</marketstat>
</evec_api>
The specific value I want is the min sell value, being 166.22. My code at current, which just retrieves all values in the document is
private void Form1_Load(object sender, EventArgs e)
{
string xmlDocPath = "http://api.eve-central.com/api/marketstat?typeid=37®ionlimit=10000002&usesystem=30000142";
XmlTextReader xmlReader = new XmlTextReader(xmlDocPath);
while (xmlReader.Read())
{
if (xmlReader.NodeType == XmlNodeType.Text)
{
textBox1.AppendText(xmlReader.Value + "\n");
}
}
}
I've tried a few different methods, like just throwing it all in a text box and taking the specific line, but that seems like a really silly solution. Most of the tutorials use console however that doesn't work for me. I feel it's probably a simple solution, but I'm yet to find one that works. Also, being fairly new to this, if there is anything terribly inefficient about this code, feel free to point it out.
Try to use LINQ to XML, it's very straightforward. Example is given below:
var doc = XDocument.Parse(xml); //use XDocument.Load if you have path to a file
string minSell = doc.Descendants("sell")
.First()
.Element("min")
.Value;
Console.WriteLine(minSell); //prints 166.22
If you wrap that XmlTextReader into a XmlDocument you can then execute an XPath query on it to retrieve the specific node you're interested in:
var doc = new XmlDocument(xmlReader);
doc.Load();
var xpath = "/marketstat/type [#id='37']/sell/min";
var myNode = doc.SelectSingleNode(xpath);
I used this code for retrieving specific value from the XML file.Now i want to retrieve all the data which are present in the XML file .Can anybody help me to find out the solution?
StorageFile xmlFile = await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFileAsync("Content1.xml");
XmlDocument xmlDoc;
xmlDoc = await XmlDocument.LoadFromFileAsync(xmlFile);
System.Xml.Linq.XDocument duc = System.Xml.Linq.XDocument.Parse(xmlDoc.GetXml());
var query=
from Date in duc.Root.Elements("Serial")
where Date.Attribute("No").Value=="1"
from Current in Date.Elements("Current")
select new {
NarratedBy=Current.Attribute("NarratedBy").Value,
value=Current.Attribute("Date").Value
};
foreach(var Date in query) {
System.Diagnostics.Debug.WriteLine("{0}\t{1}", Date.NarratedBy, Date.value);
}
You already have whole XML document loaded into duc variable.
That line is responsible for that:
System.Xml.Linq.XDocument duc = System.Xml.Linq.XDocument.Parse(xmlDoc.GetXml());
then you can just retrieve your XDocument details for example into a string variable with an XDocument extension ToString()
You have all data already:
xmlDoc = await XmlDocument.LoadFromFileAsync(xmlFile); // data loadded
System.Xml.Linq.XDocument duc = System.Xml.Linq.XDocument.Parse(xmlDoc.GetXml()); // data parsed
===================
Here is a sample code how you may do it. It is fully functional (using local string xml instead of your file) so you may run it. I added only three attributes but you may add as many as you want.
class Program {
static void Main(string[] args) {
// this is a sample string. Use your file instead
string s = "<catalog>" +
"<book id=\"bk101\" author=\"Gambardella, Matthew\" title=\"XML Developer's Guide\" genre=\"Computer\"/>" +
"<book id=\"bk102\" author=\"Ralls, Kim\" title=\"Midnight Rain\" genre=\"Fantasy\"/>" +
"</catalog>";
XmlDocument xdoc = new XmlDocument();
xdoc.LoadXml(s); // here we load data
// here we get attributes. I have three, you will add three more. Also you may want to use string array instead of variables
foreach (XmlNode task in xdoc.DocumentElement.ChildNodes)
{
string author = task.Attributes["author"].InnerText;
string title = task.Attributes["title"].InnerText;
string genre = task.Attributes["genre"].InnerText;
}
}
}