I have xml templates stored in files where there are values to be filled are written as lets say following for example
<customers>
<customer>
<name><%=user.name%></name>
<street><%=user.address.street%></street>
</customer>
</customers>
I will have user object filled in and will load this xml in string . Is there any easy way to replace related values in entire file easily ? Please consider that above is just sample and XML is really complicated with lot of constants in it and I cant use XML serialization to convert object in to XML .
Thanks
A simple regex can help here
var newXml = Regex.Replace(xml, "<%=(.+?)%>", m => MyFxn(m.Groups[1].Value));
//replace this function with yours which returns the real values. It's
//just a demo....
string MyFxn(string s)
{
var dict = new Dictionary<string, string>(){
{"user.name","name1"},
{"user.address.street","street1"}
};
return dict[s];
}
Use regex to find your data-binding expressions and replace them with values obtained using DataBinder.Eval (in ASP.NET) or through reflection from corresponding properties of your object (http://programmersunlimited.wordpress.com/2010/06/19/reflection-get-property-value-from-path/).
Related
I have an XML that implements from IXmlSerializable. I want to add a CData property so I can add binary data to the property in the XML. I'm going to pass the XML along and in another application use the binary data.
I know some characters won't be able to translate certain characters but ignoring that fact, how would I achieve this? I tried several ways from stackoverflow but I have been unsuccessful.
[XmlElementAttribute(ElementName = "test", Form = XmlSchemaForm.Unqualified)]
[XmlElement("CDataElement")]
public RawXml test
{
get
{
return test;
}
set
{
test= value;
}
}
byte[] bAry= BinaryData;
item.Property= new CustomXML(bAry);
"item" and "CustomXML" both derive from IXmlSerializable.
XML is a text based container. You cannot place binary data within a text based container without transforming it to some kind of character based translation.
Most engines will take the binary and encode it as base64 implicitly.
C# XmlWriter has the method XmlWriter.WriteBase64.
Of course you can use Convert.ToBase64String() in order to translate this yourself and pass it in as any other string value.
It should not be necessary to think about this at all...
And just to mention: No need for a CDATA section here. CDATA is something you do not need at all and which should be avoided...
You'll have to do:
Convert.ToBase64String(yourBinaryData) and pass it as a string in CData, then at the other end you'll want to use: Convert.FromBase64String(yourCDataText)
If you really wanted to send binary data over XML you could do:
<DATA>
<BINARY>
<BIT index="0">0</BIT>
<BIT index="1">0</BIT>
...
<BIT index="99">1</BIT>
</BINARY>
</DATA>
However you're better off just doing base64 encoding.
We are trying to use urls for complex querying and filtering.
I managed to get some of the simpler parst working using expression trees and a mix of regex and string manipulation but then we looked at a more complex string example
var filterstring="(|(^(categoryid:eq:1,2,3,4)(categoryname:eq:condiments))(description:lk:”*and*”))";
I'd like to be able to parse this out in to parts but also allow it to be recursive.. I'd like to get the out put looking like:
item[0] (^(categoryid:eq:1,2,3,4)(categoryname:eq:condiments)
item[1] description:lk:”*and*”
From there I could Strip down the item[0] part to get
categoryid:eq:1,2,3,4
categoryname:eq:condiments
At the minute I'm using RegEx and strings to find the | ^ for knowing if it's an AND or an OR the RegEx matches brackets and works well for a single item it's when we nest the values that I'm struggling.
the Regex looks like
#"\((.*?)\)"
I need some way of using Regex to match the nested brackets and help would be appreciated.
You could transform the string into valid XML (just some simple replace, no validation):
var output = filterstring
.Replace("(","<node>")
.Replace(")","</node>")
.Replace("|","<andNode/>")
.Replace("^","<orNode/>");
Then, you could parse the XML nodes by using, for example, System.Xml.Linq.
XDocument doc = XDocument.Parse(output);
Based on you comment, here's how you rearrange the XML in order to get the wrapping you need:
foreach (var item in doc.Root.Descendants())
{
if (item.Name == "orNode" || item.Name == "andNode")
{
item.ElementsAfterSelf()
.ToList()
.ForEach(x =>
{
x.Remove();
item.Add(x);
});
}
}
Here's the resulting XML content:
<node>
<andNode>
<node>
<orNode>
<node>categoryid:eq:1,2,3,4</node>
<node>categoryname:eq:condiments</node>
</orNode>
</node>
<node>description:lk:”*and*”</node>
</andNode>
</node>
I understand that you want the values specified in the filterstring.
My solution would be something like this:
NameValueCollection values = new NameValueCollection();
foreach(Match pair in Regex.Matches(#"\((?<name>\w+):(?<operation>\w+):(?<value>[^)]*)\)"))
{
if (pair.Groups["operation"].Value == "eq")
values.Add(pair.Groups["name"].Value, pair.Groups["value"].Value);
}
The Regex understand a (name:operation:value), it doesn't care about all the other stuff.
After this code has run you can get the values like this:
values["categoryid"]
values["categoryname"]
values["description"]
I hope this will help you in your quest.
I think you should just make a proper parser for that — it would actually end up simpler, more extensible and save you time and headaches in the future. You can use any existing parser generator such as Irony or ANTLR.
I've added functionality in my application where a DataTable is converted into XML, like so:
dtResults.WriteXml(fileName);
_x0020_ is being added instead of spaces within the outputted XML document.
Is it possible to generate XML files without the _x0020_ code? i.e. can an XML file be generated using that method or similar, and actually have the spaces preserved?
This is the DataGrid:
This is the resulting XML:
<Customers>
<Customer_x0020_Name>Sean</Customer_x0020_Name>
</Customers>
<Customers>
<Customer_x0020_Name>John</Customer_x0020_Name>
</Customers>
<Customers>
<Customer_x0020_Name>Sarah</Customer_x0020_Name>
</Customers>
<Customers>
<Customer_x0020_Name>Mark</Customer_x0020_Name>
</Customers>
<Customers>
<Customer_x0020_Name>Norman</Customer_x0020_Name>
</Customers>
The name of your column contains a space. XML element names cannot contain a space. A space is used in XML to separate element names from attribute names, for instance:
<ElementName Attribute1="value" />
The DataTable.WriteXml method tries to write out the XML file in a consistent way so that another DataTable object can later be used to load the XML and get as close to an exact copy of the original as possible. Therefore, it replaces illegal characters with their hex-values so that the illegal characters are not lost in translation.
So, if you want to write it to XML differently, you need to either:
Change the name of the column in the DataTable so that it does not contain a space
Manually output the XML yourself using XDocument, XmlDocument, XmlWriter, or XmlSerializer and format the output however you desire
Output the XML as you do now, but then run an XSLT script on it to fix the formatting
I don't think what you're wanting is possible. I don't believe an XML element name can contain a space, just like a variable name cannot contain a space. What is the reason that it needs to be a space?
If there actually needs to be a space (which I think will render the xml useless for parsing), you can simply do a find and replace in the file.
If you're storing it to read back in and display again in a DataTable, I would just rename the columns once I've read the data back in, replacing _x0020_ with spaces.
I am also facing the same problem. I am exporting data from an excel file which contains columns with space. So my columns also contains space.
So I tried the following manner.
StringWriter strXML = new StringWriter();
dtPartOriginalData.WriteXml(strXML, XmlWriteMode.IgnoreSchema, false);
strMessages = strXML.ToString().Replace("_x0020_", "");
This will replace the _x0020_ and generates xml. But you cannot construct the same datatable using this xml. Its a workaround, I thought of adding its as a suggestion. Thank you.
I have a web service that takes a single string parameter.
In my case I need to send a string which is an xml document where one of its elements contains an xml fragment (which I will use to create a file).
So for example I am sending:
<people>
<person>
<name>J Smith</name>
<value><![CDATA[<content>rest of xml document here</content>]]></value>
</person>
</people>
I used .. to create an xml file.
I was wondering if there is a better way to do this rather than using CDATA?. The CDATA files are very small (less than 20KB).
JD
There is no need to use CDATA. You can pass the xml fragment directly as is.
See, for example, http://msdn.microsoft.com/en-us/library/aa480498.aspx
UPDATE:
Steve pointed out that you have a string parameter not XmlElement parameter. I'm not sure if it would still work that way (though I feel like it could :).
Another option besides CDATA and Base64 would be Xml encoding, e.g.
var xml = new XmlDocument();
var node = xml.CreateElement("root");
node.InnerText = "<content>Anything</content>";
var xmlString = node.InnerXml; /// <content>Anything</content>
I'd suggest Base64-Encoding the XML fragment.
How about a standard HTTP POST using Mutipart/Form-Data ? Make the single parameter part of the url or querystring.
This is the more "RESTful" way of doing things.
It's just a standard file upload.
I am using Linq To XML to create XML that is sent to a third party. I am having difficulty understanding how to create the XML using Linq when part of information I want to send in the XML will be dynamic.
The dynamic part of the XML is held as a string[,] array. This multi dimensional array holds 2 values.
I can 'build' the dynamic XML up using a stringbuilder and store the values that were in the array into a string variable but when I try to include this variable into Linq the variable is HTMLEncoded rather than included as proper XML.
How would I go about adding in my dynamically built string to the XML being built up by Linq?
For Example:
//string below contains values passed into my class
string[,] AccessoriesSelected;
//I loop through the above array and build up my 'Tag' and store in string called AccessoriesXML
//simple linq to xml example with my AccessoriesXML value passed into it
XDocument RequestDoc = new XDocument(
new XElement("MainTag",
new XAttribute("Innervalue", "2")
),
AccessoriesXML);
'Tag' is an optional extra, it might appear in my XML multiple times or it might not - it's dependant on a user checking some checkboxes.
Right now when I run my code I see this:
<MainTag> blah blah </MainTag>
< ;Tag> ;< ;InnerTag> ; option1="valuefromarray0" option2="valuefromarray1" /> ;< ;Tag/> ;
I want to return something this:
<MainTag> blah blah </MainTag>
<Tag><InnerTag option1="valuefromarray0" option2="valuefromarray1" /></Tag>
<Tag><InnerTag option1="valuefromarray0" option2="valuefromarray1" /></Tag>
Any thoughts or suggestions? I can get this working using XmlDocument but I would like to get this working with Linq if it is possible.
Thanks for your help,
Rich
Building XElements with the ("name", "value") constructor will use the value text as literal text - and escape it if necessary to achieve that.
If you want to create the XElement programatically from a snippet of XML text that you want to actually be interpreted as XML, you should use XElement.Load(). This will parse the string as actual XML, instead of trying to assign the text of the string as an escaped literal value.
Try this:
XDocument RequestDoc = new XDocument(
new XElement("MainTag",
new XAttribute("Innervalue", "2")
),
XElement.Load(new StringReader(AccessoriesXML)));