Unable to remove escape character from my XML string - c#

I am building an XML string from 3 parts:
the before bit which is hard-coded
the middle bit which is created from object serialization
the after bit which is also hardcoded.
No matter what I do, I cannot remove the escape characters from it though, and this is causing failed requests when I use that XML string in the request object that it is intended for.
Code (and my attempts at this) below:
string preceedingXml = "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:enl=\"http://company.com\"><soapenv:Header/><soapenv:Body><enl:Combine>";
string afterXml = "</enl:Combine></soapenv:Body></soapenv:Envelope>";
try
{
using (var stringwriter = new System.IO.StringWriter())
{
var serializer = new XmlSerializer(this.GetType());
serializer.Serialize(stringwriter, this);
var requestXML = XDocument.Parse(stringwriter.ToString())
.Descendants("in")
.First();
string unescaped = Regex.Unescape(requestXML.ToString().Replace("\r\n", ""));
string returnValue = preceedingXml +unescaped + afterXml;
string rd = returnValue.Replace("\\'", "'");
string rd3 = returnValue.Replace(#"\", string.Empty);
string rd4 = RemoveSpecialChars(returnValue);
string rd5 = returnValue.Trim('"');
return returnValue;
}
}
The result is always the same no matter what:
<soapenv:Envelope
xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\"
xmlns:enl=\"http://company.com/product\">
<soapenv:Header/>
<soapenv:Body>
<enl:Combine>
<in
xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"
xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">
<returnAllRecords>0</returnAllRecords>
<projectName>Project</projectName>
<lhs>
<recordType>ParsedData</recordType>
<recordId>1000000</recordId>
<data>
<fields name=\"Full-Name\">
<values>John Smith</values>
etc.

Related

xml serialization encoding "&" character

I am converting an object into xml string and then into an escaped string.
public class Program
{
public static void Main(string[] args)
{
BankDetails details = new BankDetails();
var xmlstring = ToXmlString(details);
var escaped = SecurityElement.Escape(xmlstring);
}
private static string ToXmlString<T>(T input)
{
XmlSerializer xsSubmit = new XmlSerializer(typeof(T));
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
var xml = "";
ns.Add("", "");
using (var sww = new StringWriter())
{
using (XmlWriter writer = XmlWriter.Create(sww, new XmlWriterSettings()
{
OmitXmlDeclaration = true
}))
{
xsSubmit.Serialize(writer, input, ns);
xml = sww.ToString();
}
}
return xml;
}
}
public class BankDetails
{
public string MemberName = "B & A Auto";
}
How can I avoid getting & in xmlstring variable.
<BankDetails><MemberName>B & A Auto</MemberName></BankDetails>
I am looking for output something like this:
xmlstring = //<BankDetails><MemberName>B & A Auto</MemberName></BankDetails>
//and then
escaped = //<BankDetails><MemberName>B & A Auto</MemberName></BankDetails>
Working Fiddle
You can use Unicode equivalent character ie decimal or hex, & or & instead.
"B & A Auto" => "B &#038 A Auto";
You can parse your string, convert amps to their unicode equivalence and then escape those.
No, you can not. The & is a special character in XML and used for escaping other characters.
Escaped character in XML
' = &apos;
< = <
> = >
& = &
" = "

String.Replace not replacing

I'm doing some file clean up in an xml file and trying to use string.Replace to replace certain text blocks but it does not seem to be replacing the text that I am searching on.
My clean up code is follows
private Stream PrepareFile(string path)
{
string data = File.ReadAllText(path);
var newData = data.Replace("<a:FMax xmlns:b=\"http://www.w3.org/2001/XMLSchema\" i:type=\"b:string\"/>", "<a:FMax>0</a:FMax>")
.Replace("<a:KVy xmlns:b=\"http://www.w3.org/2001/XMLSchema\" i:type=\"b:string\"/>", "<a:KVy>0</a:KVy>")
.Replace("<a:Td xmlns:b=\"http://www.w3.org/2001/XMLSchema\" i:type=\"b:string\"/>", "<a:Td>0</a:Td>")
.Replace("<a:VyLim xmlns:b=\"http://www.w3.org/2001/XMLSchema\" i:type=\"b:string\"/>", "<a:VyLim>0</a:VyLim>");
var newData2 = newData.Replace("<a:VxTableSxI3_2I xmlns:b=\"http://www.w3.org/2001/XMLSchema\" i:type=\"b:string\"/>", "<a:VxTableSxI3_2I>0</a:VxTableSxI3_2I>");
byte[] bytes = Encoding.ASCII.GetBytes(newData2);
return new MemoryStream(bytes);
}
I should be able to write back to the original 'data' variable, but I split the variables out to be able to compare the strings before and after the replace. My xml file contains the following values(copied verbatim)
<a:LongitudinalTracker z:Id="i58">
<Name xmlns="http://schemas.datacontract.org/2004/07/HmsSim.EntityModule.BaseTypes" i:nil="true"/>
<a:FMax xmlns:b="http://www.w3.org/2001/XMLSchema" i:type="b:string"/>
<a:K>2</a:K>
<a:KVy xmlns:b="http://www.w3.org/2001/XMLSchema" i:type="b:string"/>
<a:Td xmlns:b="http://www.w3.org/2001/XMLSchema" i:type="b:string"/>
<a:VyLim xmlns:b="http://www.w3.org/2001/XMLSchema" i:type="b:string"/>
</a:LongitudinalTracker>
And the before and after strings look identical. I'm sure I am missing something silly, but I can't see what it is. Most of the answers to similar questions point out that the original code is not using the return value, but in this case I am definitely using the return value.
As suggested I am posting the code that ended up solving this.
private Stream PrepareFile(string path)
{
string data = File.ReadAllText(path);
var xml = XDocument.Parse(data);
XNamespace ns = "http://schemas.datacontract.org/2004/07/HmsSim.EntityModule.Entities.SimulationEntities.Track";
var longTracker = from item in xml.Descendants(ns + "LongitudinalTracker") select item;
foreach (var xElement in longTracker.Elements())
{
XNamespace nsI = "http://www.w3.org/2001/XMLSchema-instance";
if (xElement.Attribute(nsI + "type") != null)
{
xElement.Attribute(nsI + "type").Remove();
XAttribute attribute = new XAttribute(nsI + "nil", "true");
xElement.Add(attribute);
}
}
var latTracker = from item in xml.Descendants(ns + "LateralTracker") select item;
foreach (var xElement in latTracker.Elements())
{
XNamespace nsI = "http://www.w3.org/2001/XMLSchema-instance";
if (xElement.Attribute(nsI + "type") != null)
{
xElement.Attribute(nsI + "type").Remove();
XAttribute attribute = new XAttribute(nsI + "nil", "true");
xElement.Add(attribute);
}
}
Stream stream = new MemoryStream();
xml.Save(stream);
// Rewind the stream ready to read from it elsewhere
stream.Position = 0;
return stream;
}
This code works and is less brittle than the original code. As always, suggestions are welcome. Thanks to everyone who commented and led me towards this answer, I appreciate it.

Replacing Special Character with their codes

I am passing XML data to a server from a text Box, now issue is XML is giving issues with symbols like & < |. So i want to replace these symbols with their equivalent codes.
if i use string.replace function it will replace the characters recently replaced as well.
.Replace("&", "&")
.Replace("<", "<")
.Replace("|", "|")
.Replace("!", "!")
.Replace("#", "#")
As it go through complete string again and again.
So &<# will become "&#38;&#60;"
I also tried Dictionary method:
var replacements = new Dictionary<string, string>
{
{"&", "&"},
{"<", "<"},
{"|", "|"},
{"!", "!"},
{"#", "#"}
}
var output = replacements.Aggregate(input, (current, replacement) => current.Replace(replacement.Key, replacement.Value));
return output;
But same issue here as well. I also tried string builder method, but same repeating replacement issue. Any Advise?
You shouldn't be trying to escape characters manually. There are libraries and methods that are already built to do this such the SecurityElement.Escape(). It specifically escapes invalid XML characters into a known safe format that can be unescaped later.
I strongly advise using proper XML handling to build XML:
var id = 3;
var message = "&'<crazyMessage&&";
var xmlDoc = new XmlDocument();
using(var writer = xmlDoc.CreateNavigator().AppendChild())
{
writer.WriteStartElement("ROOT");
writer.WriteElementString("ID", id.ToString());
writer.WriteStartElement("INPUT");
writer.WriteElementString("ENGMSG", message);
writer.WriteEndElement(); // INPUT
writer.WriteEndElement(); // ROOT
}
var xmlString = xmlDoc.InnerXml;
Console.WriteLine(xmlString);
Ideone example
If you are using .NET 3.5 or higher, you can use Linq2Xml to build the XML, which is a bit cleaner:
var id = 3;
var message = "&'<crazyMessage&&";
var xml = new XElement("ROOT",
new XElement("ID", id),
new XElement("INPUT",
new XElement("ENGMSG", message)
)
);
var xmlString = xml.ToString();
Console.WriteLine(xmlString);
public static string Transform(string input, Dictionary<string, string> replacements)
{
string finalString = string.Empty;
for (int i = 0; i < input.Length; i++)
{
if (replacements.ContainsKey(input[i].ToString()))
{
finalString = finalString + replacements[input[i].ToString()];
}
else
{
finalString = finalString + input[i].ToString();
}
}
return finalString;
}

How to avoid XML Injection when using WriteElementString

I have the following code and throws an XML injection(Please see the highlighted text) .can some let me know how this can be removed
private string GetRecordSet(OleDbDataReader oDR)
{
XmlTextWriter xTWriter = null;
StringWriter oSWriter = null;
int iRecCnt=0;
string sName = String.Empty;
string sValue = String.Empty;
try
{
//Create Out XML
oSWriter = new StringWriter();
xTWriter = new XmlTextWriter(oSWriter);
xTWriter.Formatting = Formatting.Indented;
xTWriter.WriteStartElement("SESSION");
while(oDR.Read())
{
iRecCnt++;
sName = oDR.GetValue(0).ToString();
sValue = oDR.GetValue(1).ToString();
**xTWriter.WriteElementString(sName, sValue);**
}
xTWriter.WriteElementString("TotalRecords", iRecCnt.ToString());
xTWriter.WriteEndElement(); //ROWSET END
//Return XML string. If no records found then return empty string
string sRtrn = oSWriter.ToString();
if (iRecCnt == 0) sRtrn = string.Empty;
return sRtrn;
}
You're not sanitizing input in any way. Its XML Injectionable because of the XML metacharacters that can be used to change your code into a behavior that is unintended. Examples of the metacharacters: single quote, double quote, <, > - anything that when put through your code could actually cause the code to write xml elements or attributes that are unintended.

Inserting data at specific position in XML

I want to read an XML file and match tag </contrib-group> and write a string after this tag
string Final = File.ReadAllText(Npath);
string Oxml = path + "\\" + Oword + ".abs.xml";
if (File.Exists(Oxml))
{
StreamReader xml = new StreamReader(Oxml,Encoding.UTF8);
string xmltag = xml.ReadToEnd();
//File.OpenWrite(Oxml);
xml.Close();
StreamWriter write = new StreamWriter(Oxml, true, Encoding.UTF8);
Match tag = Regex.Match(xmltag, #"</contrib-group>");
if (tag.Success == true)
{
write.WriteLine(Environment.NewLine);
write.Write(Final);
}
}
So I need to write the string Final to the XML file called Oxml after the matched XML tag </contrib-group>
If you are willing to save the new content as a valid XML file which you can work with, you should use the XML classes for that approach, this should look like this (untested):
XmlDocument doc = new XmlDocument();
doc.Load("YourFile.xml");
XmlElement root = doc.DocumentElement;
XmlNodeList elemList = root.GetElementsByTagName("contrib-group");
for (int i=0; i < elemList.Count; i++)
{
XmlNode xnode = elemList[i];
XmlNode xnodeParent = xnode.ParentNode;
XMLNode newNode = doc.CreateNode(XmlNodeType.Element, "NodeName", "");
newNode.InnerText = "ContentInsideTheNode";
xnodeParent.InsertAfter(newNode, xnode);
}
doc.Save("YourFile.xml");
If you only need to replace the string for other purposes than saving it where having a valid XML is not an issue you can just handle it as a string and use the String.Replace (String, String) Method
string searchedTag = #"</contrib-group>";
string tagAndNewContent = #"</contrib-group>" + newContent;
string fileContentString = File.ReadAllText("YourFile.xml");
string ouput = fileContentString.Replace(searchedTag, tagAndNewContent);

Categories