How to keep xml from converting /r/n into - c#

I have here a small code:
string attributeValue = "Hello" + Environment.NewLine + " Hello 2";
XElement element = new XElement("test");
XElement subElement = new XElement("subTest");
XAttribute attribute = new XAttribute("key", "Hello");
XAttribute attribute2 = new XAttribute("key2", attributeValue);
subElement.Add(attribute);
subElement.Add(attribute2);
element.Add(subElement);
Console.Write(element.ToString());
Console.ReadLine();
I have an issue, basically the /r/n or the new line is converted in
in attribute, but I dont want to have it, I want to keep it /r/n as when I use this XML with the Microsoft Word documents template, the new lines are not implemented, although it is multilined text, in word document I only get the spaces. But no new lines :/
Anyone has any idea?
Although i've set the allow multi line int he property of the field in the template.

Actually the behaviour you get with
is the same than the one of Environment.NewLine. You can do a simple test to confirm this (add two TextBoxes to your Form with the Multiline property set to True: textBox1 and textBox2):
textBox1.Text = element.ToString(); //
string text = element.ToString().Replace("
", Environment.NewLine);
textBox2.Text = text; ///r/n
On the other hand, if you want to avoid the
part anyway (for example: because of wanting to output the given string to an external program not working on .NET), you can just rely on the aforementioned Replace after dealing with XElement and new lines.

Related

how to remove a string in a line of Multiline textbox c#

i have the data bellow in my multiline textbox in my form
what i want is remove the " -" from that line, i wanna just to remove in that first line but without changing the rest of textbox values
what i have tried but without sucess
Textbox1.Lines[0] = Textbox1.Lines[0].Replace(" -", "");
According to the documentation for the Lines property:
Note
By default, the collection of lines is a read-only copy of the lines in the TextBox. To get a writable collection of lines, use code similar to the following: textBox1.Lines = new string[] { "abcd" };
So, it seems we need to assign it a whole new array, not just modify an existing array value. Something like this should do the trick:
var newLines = Textbox1.Lines; // Capture the read-only array locally
newLines[0] = newLines[0].Replace(" -", ""); // Now we can modify a value
Textbox1.Lines = newLines; // And reassign it to our textbox

String.Split not working to get values

I have an XML which is passes as a string variable to me. I want to get the value of specific tags from that XML. Following is the XML I have and what I'm trying to achieve:
<code>
string xmlData = #"
<HEADER>
<TYPE>AAA</TYPE>
<SUBTYPE>ANNUAL</SUBTYPE>
<TYPEID>12345</TYPEID>
<SUBTYPEID>56789</SUBTYPEID>
<ACTIVITY>C</ACTION>
</HEADER>";
var typeId = data.Split("<TYPEID>")[0]; //Requirement
var activity = data.Split("<ACTIVITY>")[0]; //Requirement
</code>
I know string.Split(); doesn't work here as it requires a single character only. Other alternate is to use regex which seems a bit threatening to me. Although I have tried to work with it but doesn't getting the desired result. Can someone help with the regex code?
You should have used XML Parsing to get the values but since you are trying split to split a string from a string and not char you can choose
string typeId = xmlData.Split(new string[] { "<TYPEID>" }, StringSplitOptions.None)[1];
string typeIdVal = typeId.Split(new string[] { "</TYPEID>" }, StringSplitOptions.None)[0];
and it looks very neat and clean with XML Parsing
XmlDocument xmlDoc= new XmlDocument();
xmlDoc.Load("yourXMLFile.xml");
XmlNodeList XTypeID = xmlDoc.GetElementsByTagName("TYPEID");
string TypeID = XTypeID[0].InnerText;
You can also choose SubString like
string typeidsubstr = xmlData.Substring(xmlData.IndexOf("<TYPEID>") + 8, xmlData.IndexOf("</TYPEID>") - (xmlData.IndexOf("<TYPEID>") + 8));
I used +8 because the length of <TYPEID> is 8 you can also choose it string.length to evaluate the result.
You can use XML Linq objects to parse these.
NB: There is a typo in the ACTIVITY element, the closing tag should be /ACTIVITY, not /ACTION! (I've corrected below)
string xmlData = #"<HEADER>
<TYPE>AAA</TYPE>
<SUBTYPE>ANNUAL</SUBTYPE>
<TYPEID>12345</TYPEID>
<SUBTYPEID>56789</SUBTYPEID>
<ACTIVITY>C</ACTIVITY>
</HEADER>";
var doc = XDocument.Parse(xmlData);
var typeId = doc.Root.Elements("TYPEID").First().Value;
var activity = doc.Root.Elements("ACTIVITY").First().Value;

OpenXML Find Variables within Word doc and replace them

I need to search a document for strings enclosed in <>. So if the application finds the variable within the document, it replaces that variable with DateTime.Today.ToShortDateString(). For instance:
string filename = "C:\\Temp\\" + appNum + "_ReceiptOfApplicationLtr.docx";
if (File.Exists((string)filename))
{
using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(filename, true))
{
var body = wordDoc.MainDocumentPart.Document.Body;
foreach (var text in body.Descendants<Text>())
{
if (text.Text == "<TodaysDate>")
{
text.Text = text.Text.Replace("<TodaysDate>", DateTime.Today.ToShortDateString());
}
}
using (StreamWriter sw = new StreamWriter(wordDoc.MainDocumentPart.GetStream(FileMode.Create)))
{
sw.Write(filename);
}
}
}
Well when it searches the Descendants Text, it finds the first <, then TodaysDate, finally >. The issue being it won't find the string <TodaysDate>. Can anyone help me out?
Open XML can store text in different text tags inside the same run. What I would do if I were you is just find the Run where your string is stored and use the InnerText property to find all the text inside that run.
For example:
Run runToFind = body.Descendants<Run>()
.FirstOrDefault(r => r.Innertext.Contains("<TodaysDate>");
Then you can replace the Run with another one:
runToFind.Parent.Replace(new Run(new Text(DateTime.Now.ToShortDateString())),runToFind);
For anyone still struggling with this - you can check out this library
https://github.com/antonmihaylov/OpenXmlTemplates
With it instead of searching for special tags in the text (because of the problems specified in the comment of Thomas Barnekow), you add a Content control in the document and in the tag name of the content control you specify the name of the variable you want to replace.
You can then feed JSON data or a regular C# dictionary object and the text will get replaced.
Note - I am the maker of that library, but i have no financial gain from it - it is open sourced and under active development (and always looking for contributors!)

How to add mixed Text and XElements on XElement value

I am trying to add as value to an XElement mixed text and inline elements.
For example when setting the string "this is a mixed text <foo>and</foo> inline element." the XElement.Nodes to be able to return the text node as XmlNodeType.Text & the element as XmlNodeType.Element.
Thanks in advance.
Use e.g. new XElement("parent", "this is a mixed text ", new XElement("foo", "and"), " inline element.") respectively element.Add("this is a mixed text ", new XElement("foo", "and"), " inline element.").
If you have a plain string then use e.g.
element.Add(XElement.Parse("<root>" + "this is a mixed text <foo>and</foo> inline element." + "</root>").Nodes());

Form control as an xml value

I have this example code in my c# win form...
List<string> listFurniture = new List<string>();
XDocument xml = XDocument.Load(Application.StartupPath + #"\Furniture.xml");
foreach (XElement quality in xml.Descendants("Quality"))
listFurniture.Add(quality.Value);
maintextbox.Text = listFurniture[0];
... And this example xml
<Furniture>
<Table>
<Quality>textbox1.Text + "and" + textbox2.Text + "but" + textbox3.Text</Quality>
...
</Table>
</Furniture>
My dilemma is, the maintextbox is producing the actual string "textbox1.Text", instead of the value of textbox1.
I want the xml value to be read as:
maintextbox.Text = textbox1.Text + "and" + textbox2.Text + "but" + textbox3.Text;
not as:
maintextbox.Text = "textbox1.Text + "and" + textbox2.Text + "but" + textbox3.Text";
I tried using a text file as well with StreamReader and I got the same result.
The reason for coding my project this way is because the sequence of the textboxes changes and so does the "and" and the "but". When that change happens, I wouldn't have to rewrite the code and recompile the program. I would just make the changes in xml.
There is all OK with xml parsing in your solution. What you need is processing of Quality strings.
string[] parts = quality.Split('+');
Regex regex = new Regex(#"^""(.*)""$");
var textBoxes = Controls.OfType<TextBox>().ToList();
for (int i = 0; i < parts.Length; i++)
{
string part = parts[i].Trim();
var match = regex.Match(part);
if (match.Success)
{
parts[i] = match.Groups[1].Value;
continue;
}
var textBox = textBoxes.FirstOrDefault(tb => tb.Name + ".Text" == part);
if (textBox != null) // possibly its an error if textbox not found
parts[i] = textBox.Text;
}
mainTextBox.Text = String.Join(" ", parts);
What happened here:
We split quality string by + chars to get array of string parts
With regular expression we verify if part looks like something in quotes "something". If yes, then it will be or, and or other connective word
And last, we check all textboxes for matching name of textbox in quality string part. If it matches, then we replace part with text from textbox
We join parts to get result string
BTW you can parse Xml in one line:
var listFurniture = xml.Descendants("Quality")
.Select(q => (string)q)
.ToList();
Update:
Since I received a comment to explain the code a bit; I'll explain it a bit.
First, XML as a language is designed for structure. That structure and ease; provides the flexibility and power to quickly parse data between languages or applications seamless. Your original question states that your textbox is producing a string value of your code textbox.text.
The XML need to be structured; an example structure would be:
<Furniture>
<Table>
<Color> Red </Color>
<Quality> 10 </Quality>
<Material> Wood </Material>
</Table>
</Furniture>
So if you were to read your XML it would be finding the root tag. All other components would be nodes. These nodes need to be index, or siphoned through to attain the proper correlation you would like represented into your textbox.
That is what this code is doing; I'll break it down through each step.
// String you will format with the XML Structure.
StringBuilder output = new StringBuilder();
The next part will be as follows:
// Create an XML Reader, by wrapping it in the 'using' it will ensure once your done the object is disposed of. Rather then leaving the connection to your document open.
using (XmlReader reader = XmlReader.Create(new StringReader(xmlString)))
{
// We will read our document to the following; hold to that attribute. The attribute is identifying the node and all of the child elements that reside within it: So in our case Table.
reader.ReadToFollowing("Table");
reader.MoveToFirstAttribute();
string color = reader.Value;
output.AppendLine("The color of the table " + color);
// As you can see there isn't anything fancy here, it reads to our root node. Then moves to the first child element. Then it creates a string and appends it. Keep in mind we are using our StringBuilder so we are just appending to that structure.
reader.ReadToFollowing("Material");
output.AppendLine("The material: " + reader.ReadElementContentAsString());
// Same result as we used earlier; just a different method to attain our value.
}
// Now we output our block.
OutputTextBlock.Text = output.ToString();
Now all the data is pushed into a string, obviously you can use the above code with a textbox to retrieve those values as well.
That is how you correctly receive XML into your application; but you mentioned two things earlier. So it sounds like your trying to use the textbox to physically write to the document, which can be done through the XmlWriter.
But the reason you also keep receiving your textbox because as far as the textbox is concerned textbox.text is associated to the value. Your structure is stating this string is the value.
In order to achieve your goal; you would have a method to write the value to the document. Then another to read it; so that it properly transitions the data in and out of your document and is represented correctly.
<Quality>Textbox1.Text</Quality> That doesn't allow the textbox value to automatically be read into your document and textbox. Your assigning a string value into the node. You would physically have to write to the document the values before it can be read.
The MSDN has examples of how to properly parse the data; hopefully I've clarified some of the reasons in which you are having your issue.
More code; straight from MSDN:
Right off the MSDN:
StringBuilder output = new StringBuilder();
String xmlString =
#"<?xml version='1.0'?>
<!-- This is a sample XML document -->
<Items>
<Item>test with a child element <more/> stuff</Item>
</Items>";
// Create an XmlReader
using (XmlReader reader = XmlReader.Create(new StringReader(xmlString)))
{
XmlWriterSettings ws = new XmlWriterSettings();
ws.Indent = true;
using (XmlWriter writer = XmlWriter.Create(output, ws))
{
// Parse the file and display each of the nodes.
while (reader.Read())
{
switch (reader.NodeType)
{
case XmlNodeType.Element:
writer.WriteStartElement(reader.Name);
break;
case XmlNodeType.Text:
writer.WriteString(reader.Value);
break;
case XmlNodeType.XmlDeclaration:
case XmlNodeType.ProcessingInstruction:
writer.WriteProcessingInstruction(reader.Name, reader.Value);
break;
case XmlNodeType.Comment:
writer.WriteComment(reader.Value);
break;
case XmlNodeType.EndElement:
writer.WriteFullEndElement();
break;
}
}
}
}
OutputTextBlock.Text = output.ToString();
or
StringBuilder output = new StringBuilder();
String xmlString =
#"<bookstore>
<book genre='autobiography' publicationdate='1981-03-22' ISBN='1-861003-11-0'>
<title>The Autobiography of Benjamin Franklin</title>
<author>
<first-name>Benjamin</first-name>
<last-name>Franklin</last-name>
</author>
<price>8.99</price>
</book>
</bookstore>";
// Create an XmlReader
using (XmlReader reader = XmlReader.Create(new StringReader(xmlString)))
{
reader.ReadToFollowing("book");
reader.MoveToFirstAttribute();
string genre = reader.Value;
output.AppendLine("The genre value: " + genre);
reader.ReadToFollowing("title");
output.AppendLine("Content of the title element: " + reader.ReadElementContentAsString());
}
OutputTextBlock.Text = output.ToString();

Categories