Is it possible to add literal XML data within a C# code file? I'm currently using a multiline string literal but it gets messy as you can see. Any better way of doing this?
string XML = #"<?xml version=""1.0"" encoding=""utf-8""?>
<customUI xmlns=""http://schemas.example.com/customui"">
<toolbar id=""save"">
</toolbar>
</customUI>";
XML literals are a feature of VB.NET, not C#.
What you have posted is as close as you can get in C#.
You may want to consider replacing the embedded double quotes with single quotes though (as both types are valid XML).
For larger amounts of XML you may want to consider the answer from Marc - using an XML file (loaded once and stored in memory), so you can take advantage of the XML editor.
If the XML is big enough to get in the way, consider using a flat .xml file instead, either loaded from disk, or embedded as a resource. As long as you only load it once (perhaps in a static constructor) this will make no difference to performance. It will be considerably easier to maintain, as it will use the IDE's XML file editor. And it won't get in the way of your code.
With reference to my comment, I couldn't recall where I saw this, but I finally found the XmlBuilder link.
In retrospect, it seems Linq to XML would be your best bet. It's cleaner, faster and more maintainable than concatenating XML strings:
XNamespace ns = "http://schemas.example.com/customui";
XDocument doc = new XDocument(
new XDeclaration("1.0", "utf-8", "yes"),
new XElement(ns + "customUI",
new XElement(ns + "taskbar",
new XAttribute("id", "save"))
)
);
var stringWriter = new StringWriter();
doc.Save(stringWriter); //Write to StringWriter, preserving the declaration (<?xml version="1.0" encoding="utf-16" standalone="yes"?>)
var xmlString = stringWriter.ToString(); //Save as string
doc.Save(#"d:\out.xml"); //Save to file
As a peculiar, and very case-specific solution, if you happen to be working in an ASP.NET environment using the Razor engine, in a CSHTML file you can:
Func<MyType, HelperResult> xml = #<root>
<item>#(item.PropertyA)</item>
<item>#(item.PropertyB)</item>
<item>#(item.PropertyC)</item>
</root>;
With the addition of an extension method:
public static XDocument ToXDocument<T>(this Func<T, HelperResult> source, T item)
{
return XDocument.Parse(source(item).ToHtmlString());
}
You can then:
XDocument document = xml.ToXDocument(new MyType() {
PropertyA = "foo",
PropertyB = "bar",
PropertyC = "qux",
});
Again, peculiar? Yes. Case-specific? Yes. But it works, and gives great Intellisense. (mind you, it also will give a bunch of validity warnings, depending on the document validation version)
The closest we could have in C# would be through LINQ, something like that:
var xml = XDocument.Load(
new StringReader(#"<Books>
<Book author='Dan Brown'>The Da Vinci Code</Book>
<Book author='Dan Brown'>The Lost Symbol</Book>
</Books>"));
var query = from book in xml.Elements("Books").Elements("Book")
where book.Attribute("author").Value == "Dan Brown"
select book.Value;
foreach (var item in query) Console.WriteLine(item);
Related
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
if i were to say create a function:
public static string createProduct(string pName, decimal pPrice)
{string postData = #"<?xml version=""1.0"" encoding=""UTF-8""?
<product>
<name>?</name>
<price>?</price>
</product>";
....some other codes...}
i have tried googling it but have not found any clear answer...
and sorry i'm kinda new to xml and c#, so how do i insert pName and pPrice into xml without upsetting visual studio?
would really appreciate help from you guys...tia!
var str = new XElement("product",
new XElement("name", pName),
new XElement("price", pPrice))
.ToString();
System.Xml.Linq Namespace and XElement class are good places to start to read and easier to use than System.Xml namespace
public static string createProduct(string pName, decimal pPrice)
{string postData = #"<?xml version=""1.0"" encoding=""UTF-8""?
<product>
<name>" + pName + #"</name>
<price>" + pPrice+ #"</price>
</product>";
....some other codes...}
I recommend that you take a look at constructing the XML document not by string concatenation as it is quite unreliable (what if pName contains angle brackets?). Try looking at the XElement (XLINQ) API.
A Google search for how to add variables to a string in c# yielded this page as the first result: Strings (C# Programming Guide)
You can use the + operator to concatenate strings (that compiles to the string.Concat method). Or, you could use string.Format; for more information on that, see the page on composite formatting. This approach is only suitable for the simplest of small XML fragments.
You also have several options in the form of different sets of classes that will help you build and work with XML, most of which are to be found in the System.Xml namespaces. These classes will produce well-formed XML, taking care of small details that you might overlook (for example, special handling of certain characters). Unfortunately, I don't know of a good discussion of the pros and cons of each approach.
I'd really recommend not doing this by string concatenation. There are a number of different ways to accomplish this that will yield better (as in less likely to produce malformed XML) results.
Via XmlTextWriter:
string xmlString = null;
using (StringWriter xmlOutput = new StringWriter())
using(XmlTextWriter xmlWriter = new XmlTextWriter(xmlOutput))
{
xmlWriter.WriteStartDocument();
xmlWriter.WriteStartElement("product");
xmlWriter.WriteElementString("name", pName);
xmlWriter.WriteElementString("price", pPrice);
xmlWriter.WriteEndElement();
xmlString = xmlOutput.ToString();
}
Using XmlDocument:
string xmlString = null;
using (StringWriter xmlOutput = new StringWriter())
{
XmlDocument xmlDocument = new XmlDocument();
XmlElement productElement = xmlDocument.CreateElement("product");
XmlElement nameElement = xmlDocument.CreateElement("name");
nameElement.InnerText = pName;
XmlElement priceElement = xmlDocument.CreateElement("price");
priceElement.InnerText = pPrice;
productElement.AppendChild(nameElement);
productElement.AppendChild(priceElement);
xmlDocument.AppendChild(productElement);
xmlDocument.Save(xmlOutput);
xmlString = xmlOutput.ToString();
}
Using XDocument (requires that you are using .NET 3.5 or higher):
XDocument xml = new XDocument(
new XElement("product",
new XElement("name", pName),
new XElement("price", pPrice)
)
);
string xmlString = xml.ToString();
Note that of these methods only the one using XmlTextWriter will stream, which may be important for very large XML composition. If you are using .NET 3.5 or higher and are not dealing with very large XML composition, I would give preference to XDocument as it's a lot more readable and simpler to use.
Is it possible to add literal XML data within a C# code file? I'm currently using a multiline string literal but it gets messy as you can see. Any better way of doing this?
string XML = #"<?xml version=""1.0"" encoding=""utf-8""?>
<customUI xmlns=""http://schemas.example.com/customui"">
<toolbar id=""save"">
</toolbar>
</customUI>";
XML literals are a feature of VB.NET, not C#.
What you have posted is as close as you can get in C#.
You may want to consider replacing the embedded double quotes with single quotes though (as both types are valid XML).
For larger amounts of XML you may want to consider the answer from Marc - using an XML file (loaded once and stored in memory), so you can take advantage of the XML editor.
If the XML is big enough to get in the way, consider using a flat .xml file instead, either loaded from disk, or embedded as a resource. As long as you only load it once (perhaps in a static constructor) this will make no difference to performance. It will be considerably easier to maintain, as it will use the IDE's XML file editor. And it won't get in the way of your code.
With reference to my comment, I couldn't recall where I saw this, but I finally found the XmlBuilder link.
In retrospect, it seems Linq to XML would be your best bet. It's cleaner, faster and more maintainable than concatenating XML strings:
XNamespace ns = "http://schemas.example.com/customui";
XDocument doc = new XDocument(
new XDeclaration("1.0", "utf-8", "yes"),
new XElement(ns + "customUI",
new XElement(ns + "taskbar",
new XAttribute("id", "save"))
)
);
var stringWriter = new StringWriter();
doc.Save(stringWriter); //Write to StringWriter, preserving the declaration (<?xml version="1.0" encoding="utf-16" standalone="yes"?>)
var xmlString = stringWriter.ToString(); //Save as string
doc.Save(#"d:\out.xml"); //Save to file
As a peculiar, and very case-specific solution, if you happen to be working in an ASP.NET environment using the Razor engine, in a CSHTML file you can:
Func<MyType, HelperResult> xml = #<root>
<item>#(item.PropertyA)</item>
<item>#(item.PropertyB)</item>
<item>#(item.PropertyC)</item>
</root>;
With the addition of an extension method:
public static XDocument ToXDocument<T>(this Func<T, HelperResult> source, T item)
{
return XDocument.Parse(source(item).ToHtmlString());
}
You can then:
XDocument document = xml.ToXDocument(new MyType() {
PropertyA = "foo",
PropertyB = "bar",
PropertyC = "qux",
});
Again, peculiar? Yes. Case-specific? Yes. But it works, and gives great Intellisense. (mind you, it also will give a bunch of validity warnings, depending on the document validation version)
The closest we could have in C# would be through LINQ, something like that:
var xml = XDocument.Load(
new StringReader(#"<Books>
<Book author='Dan Brown'>The Da Vinci Code</Book>
<Book author='Dan Brown'>The Lost Symbol</Book>
</Books>"));
var query = from book in xml.Elements("Books").Elements("Book")
where book.Attribute("author").Value == "Dan Brown"
select book.Value;
foreach (var item in query) Console.WriteLine(item);
I'm writing an application in C#. I already an .xml file that is not empty and I want to add new values to it, without deleting the existing values.
I have tried this code:
First:
FileStream docNewUser = new FileStream(#"C:\\MyApp\\MySubDir\\Data\\" + pr + ".xml", FileMode.Open);
XmlTextWriter xmlNewUser = new XmlTextWriter(docNewUser, null);
xmlNewUser.WriteStartDocument();
xmlNewUser.WriteStartElement("RootEl");//root
xmlNewUser.WriteStartElement("Zapis");
xmlNewUser.WriteStartElement("Name");
xmlNewUser.WriteString(txtEnterName.Text);
xmlNewUser.WriteEndElement();
xmlNewUser.WriteEndElement();//end of zapis
this.Close();
Second:
FileStream docNewUser = new FileStream(#"C:\\MyApp\\MySubDir\\Data\\" + pr + ".xml", FileMode.Open);
XmlTextWriter xmlNewUser = new XmlTextWriter(docNewUser, null);
xmlNewUser.WriteStartDocument();
xmlNewUser.WriteStartElement("RootEl");//root-ot
xmlNewUser.WriteStartElement("Zapis");
xmlNewUser.WriteStartElement("Name");
xmlNewUser.WriteString(txtEnterName.Text);
xmlNewUser.WriteEndElement();
xmlNewUser.WriteEndElement();//end of zapis
xmlNewUser.WriteElementString("Ime", null, txtEnterName.Text);
this.Close();
Third:
FileStream docNewUser = new FileStream(#"C:\\MyApp\\MySubDir\\Data\\" + pr + ".xml", FileMode.Open);
XmlTextWriter xmlNewUser = new XmlTextWriter(docNewUser, null);
xmlNewUser.WriteStartDocument();
xmlNewUser.WriteStartElement("Zapis");
xmlNewUser.WriteStartElement("Name");
xmlNewUser.WriteString(txtEnterName.Text);
xmlNewUser.WriteEndElement();
xmlNewUser.WriteEndElement();//end of zapis
xmlNewUser.WriteElementString("Ime", null, txtEnterName.Text);
this.Close();
I think the problem is that the stream doesn’t know where to put the new value.
some more information: the root element is already entered.
If your .NET version supports it, use LINQ to XML. (Caveat: I'm not an expert, and there's probably a more elegant way to write this.)
// Without error handling
var root = XElement.Load(#"C:\Users\TrueWill\Downloads\Foo.xml");
var product =
(from item in root.Elements("item")
where item.Element("name").Value == "Product1"
select item)
.Single();
product.Add(new XElement("size", "small"));
root.Save(#"C:\Users\TrueWill\Downloads\FooCopy.xml");
My test file (before):
<?xml version="1.0" encoding="utf-8"?>
<test>
<item><name>Product1</name></item>
<item><name>Product2</name></item>
</test>
My test file copy (after) (I copied rather than replacing):
<?xml version="1.0" encoding="utf-8"?>
<test>
<item>
<name>Product1</name>
<size>small</size>
</item>
<item>
<name>Product2</name>
</item>
</test>
When you write XML to a file this way, it always overwrites what was in the file before. If you want to write to it using XmlTextWriter, you would have to copy the current content first, and write the new elements at the proper position. Don't forget that you can't read from and write to the same file at the same time, so you have to use a temporary file and overwrite the original with it. Or you read the whole file into a string first. Or write your result into a string first.
But a better solution might be to use XDocument (or XmlDocument) to load the whole document, modify it and then save it. (Doing this is not a good idea if the XML file is huge.)
Use XmlDocument:
XmlDocument doc = new XmlDocument();
doc.Load("filepath");
XmlNode node = doc["MainNode"]["subnode1"]["subnode2"]; //to fetch the node after which you'd like to add something.
XmlElement stuffToAdd = doc.CreateNode("nodename");
stuffToAdd.InnerText = "the value of your added node";
node.AddChild(stuffToAdd);
doc.Save("filepath");
I'm doing this out of memory, so the names of the methods are aproximate.
As said in another answer, loading big XML files using XmlElement can be costy, because it is fully loaded in memory when you call Load().
Is there a reason you are using XmlTextWriter? I find the LINQ to XML alternatives much easier.
your code would be something like below;
XElement el = new XElement("Zapis");
el.Add(new XElement("Name",txtEnterName.Text))
el.Save(#"C:\\MyApp\\MySubDir\\Data\\" + pr + ".xml")
This is the question I posted :
Hi, I have an XSLT code which needs to take parameters (say one or two) from C# code .. (If you want to know, why I need to do this, then let me explain, I have to parse an input XML from certain external application, however I need to edit data of some tags taking the values of some other application which could be defined in complex C# code, I don't have to worry about it) .. for the time being and for demo purpose, I need to declare some strings and pass them to XSLT following the action of triggering the transformation.
I tried to search google, but didn't work. If you get to know ANYTHING regarding this, please send me corresponding link or information ..
As I am not familiar with C# (thats the reason stuck with problem) simpler coding would help a lot ..
And also please specify which "project type" should I select ..
thanks in advance ..
And the solution is here:
http://msdn.microsoft.com/en-us/library/system.xml.xsl.xsltargumentlist.addparam.aspx
simple and works very conveniently ..
thanQ MandoMando and thanQ "stackoverflow"
Generally speaking, it's not necessary to create DOM objects like XmlDocument or XDocument to execute transforms.
XslCompiledTransfrom xslt = new XsltCompiledTransform()
xslt.Load(transformPath);
XsltArgumentList args = new XsltArgumentList();
args.AddParam("name", "myNamespace", value)
using (XmlReader xr = XmlReader.Create(inputPath))
using (XmlWriter xw = XmlWriter.Create(outputPath))
{
xslt.Transform(xr, args, xw);
}
Note that the Create() methods of XmlReader and XmlWriter have a formidable number of overloads. I use XmlWriter.Create(Console.Out) a lot when I'm prototyping.
Have your looked at this article? It talks about passing params to xslt in C#. I believe it is possible to do.
Quick and dirty:
XmlDocument x = new XmlDocument();
x.Load("yourxmldoc.xml");
XslTransform t = new XslTransform();
XsltArgumentList xslArg = new XsltArgumentList();
xslArg.AddParam("parameterName", "", parameterValue);
StringWriter swEndDoc = new System.IO.StringWriter();
t.Load("yourdoc.xslt");
t.Transform(x, xslArg, swEndDoc, null);
String output = swEndDoc.ToString();
This is fairly straightforward - note that I'm using XDocument and XslCompiledTransform:
XDocument xmlDocument = XDocument.Load(fromSource); // Or whatever means to get XML
XsltArgumentList xslArgs = new XsltArgumentList();
// For as many params as you need
xslArgs.AddParam("paramName", "", "paramValue");
// Create and load an XSLT transform - with params matching param names above
XslCompiledTransform t = new XslCompiledTransform();
t.Load(XSLTPath);
StringWriter outputDoc = new System.IO.StringWriter();
t.Transform(xmlDocument.CreateReader(), xslArgs, outputDoc);
String output = outputDoc.ToString();