I want to save a WCF request as file to a catalog, but when the file(xml) is created from the XmlSerializer it adds a Node to the XML file which I do not want. Called ("ProjectInRequest"). I do not want to have this node in the created output file.
How can I remove it in the most sufficent way?
I have tried to load the whole document in XmlDocument where the file should be created, but the creation of the file does not happen until the response is returned. There fore the whole service fails.
namespace SymbrioProjectIn
{
public partial class SymbrioProjectIn_v1
{
public ProjectInResponse GetSymbrioProjectInRequest(ProjectInRequest request)
{
if (request == null || request.SymbrioXMLProjectIn.Project == null && request.SymbrioXMLProjectIn.Routing == null )
{
throw new ApplicationException("Request is null: You need to send info in request.");
}
else
{
try
{
//All we want to do is take the Request that SAP sends and store it to a file catalog.
//We can after that use BizTalk to move the file too another sftp catalog for Symbrio
string path = AppDomain.CurrentDomain.BaseDirectory;
String dir = Path.GetDirectoryName(path);
dir += "\\ProjectIn_Data";
string filename = dir + "\\ProjectIn.xml";
if (!Directory.Exists(dir))
Directory.CreateDirectory(dir); // inside the if statement
//XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
//Add an empty namespace and empty value
//ns.(string.Empty, string.Empty);
//XElement ProjectInRequest = new XElement("ProjectInRequest");
//ProjectInRequest.RemoveAll();
/*XmlAttributes ignore = new XmlAttributes() { XmlIgnore = true };
XmlAttributeOverrides overrides = new XmlAttributeOverrides();
overrides.Add(typeof(ProjectInRequest), "ProjectInRequest", ignore);*/
XmlSerializer ser = new XmlSerializer(request.GetType(), new XmlRootAttribute("ProjectInRequest").ElementName); //Tried som code from internet not sure what it does
FileStream fs = File.Open(
filename,
FileMode.OpenOrCreate,
FileAccess.Write,
FileShare.ReadWrite);
ser.Serialize(fs, request);
var response = new SymbrioProjectIn.ProjectInResponse{
SymbrioXMLProjectIn = request.SymbrioXMLProjectIn
};
//Looks like xmlSerialiser creates some type of namespace which I do not want.
//Create our own namespaces for the output
XmlDocument XDoc = new XmlDocument();
XDoc.Load(#"D:\ServiceArea\SymbrioProjectIn\ProjectIn_Data\ProjectIn.xml");
XmlNodeList RemoveNodeProjectInRequest = XDoc.GetElementsByTagName("ProjectInRequest");
foreach (XmlNode Node in RemoveNodeProjectInRequest)
{
Node.ParentNode.RemoveChild(Node);
}
XDoc.Save(#"D:\ServiceArea\SymbrioProjectIn\ProjectIn_Data\ProjectIn.xml");
return response;
}
catch (Exception ex)
{
//throw new Exception(ex.Message);
throw new ApplicationException(ex.Message);
}
}
}
}
}
The file that is created looks like this
<?xml version="1.0"?>
<ProjectInRequest xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="ProjectInRequest">
<SymbrioXMLProjectIn>
<Routing SourceValue="?" SourceType="?" DestinationValue="?" DestinationType="?" xmlns="http://www.symbrio.com/schemas/symbrioprojectin20133" />
<Project xmlns="http://www.symbrio.com/schemas/symbrioprojectin20133">
<CompanyCode>?</CompanyCode>
<DivisionCode>?</DivisionCode>
<MainProjectNo>?</MainProjectNo>
<ProjectNo>?</ProjectNo>
<ProjectName>?</ProjectName>
<ProjectType>?</ProjectType>
<PLCode>?</PLCode>
<EmploymentNo>?</EmploymentNo>
<Active>?</Active>
<ActiveStart>?</ActiveStart>
<ActiveEnd>?</ActiveEnd>
<DeliveryAddress>?</DeliveryAddress>
<DeliveryPostalCode>?</DeliveryPostalCode>
<DeliveryCity>?</DeliveryCity>
<DeliveryAddressNoteText>?</DeliveryAddressNoteText>
<AccountRef1>?</AccountRef1>
<AccountRef2>?</AccountRef2>
<AccountRef3>?</AccountRef3>
<AccountRef4>?</AccountRef4>
<RegisteredDate>?</RegisteredDate>
<Closed>?</Closed>
</Project>
</SymbrioXMLProjectIn>
</ProjectInRequest>
What I want is this,
<?xml version="1.0" encoding="utf-8"?>
<SymbrioXMLProjectIn>
<Routing SourceValue="str1234" SourceType="str1234" DestinationValue="str1234" DestinationType="str1234" />
<Project>
<CompanyCode>str1234</CompanyCode>
<DivisionCode>str1234</DivisionCode>
<MainProjectNo>str1234</MainProjectNo>
<ProjectNo>str1234</ProjectNo>
<ProjectName>str1234</ProjectName>
<ProjectType>str1234</ProjectType>
<PLCode>str1234</PLCode>
<EmploymentNo>str1234</EmploymentNo>
<Active>str1234</Active>
<ActiveStart>str1234</ActiveStart>
<ActiveEnd>str1234</ActiveEnd>
<DeliveryAddress>str1234</DeliveryAddress>
<DeliveryPostalCode>str1234</DeliveryPostalCode>
<DeliveryCity>str1234</DeliveryCity>
<DeliveryAddressNoteText>str1234</DeliveryAddressNoteText>
<AccountRef1>str1234</AccountRef1>
<AccountRef2>str1234</AccountRef2>
<AccountRef3>str1234</AccountRef3>
<AccountRef4>str1234</AccountRef4>
<RegisteredDate>str1234</RegisteredDate>
<Closed>str1234</Closed>
</Project>
</SymbrioXMLProjectIn>
ProjectInRequest - Node does not exist.
I might have missed something if so please point it out.
Thanks in advance.
use xpath to extract the record you wanted
//*[local-name()='SymbrioXMLProjectIn']
Nvm found the solution, I XmlSeralized wrong the correct way should have been
XmlSerializer ser = new XmlSerializer(request.SymbrioXMLProjectIn.GetType());
the bad way was
XmlSerializer ser = new XmlSerializer(request.GetType());
Will leave this here if anyone does a dummy misstake like me.
Related
I have changed the code when trying to fix Veracode error for Improper Restriction of XML External Entity Reference, but it did not fix it.
Here is the code I have now:
XmlDocument xmlDoc=new XmlDocument();
using (System.IO.MemoryStream xmlstream = new System.IO.MemoryStream
(Encoding.Default.GetBytes(dsEQ.GetXml().ToString())))
{
XmlReaderSettings settings = new XmlReaderSettings();
settings.DtdProcessing = DtdProcessing.Prohibit;
using (XmlReader xmlreader = XmlReader.Create(xmlstream, settings))
{
try
{
xmlDoc.Load(xmlreader);
}
catch(XmlException e)
{
Connection.LogError(e.ToString(), e.Message);
}
}
}
However, Veracode still point out on this section of code with the same error message.
Is there anything else that I should do to fix it? We do not have any external references, everything is through intranet.
Set XmlResolver to null:
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.XmlResolver = null;
Set XmlResolver = null will fix the issue.
static void LoadXML()
{
string xml = "<?xml version=\"1.0\" ?><!DOCTYPE doc
[<!ENTITY win SYSTEM \"file:///C:/Users/user/Documents/testdata2.txt\">]
><doc>&win;</doc>";
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.XmlResolver = null; // Setting this to NULL disables DTDs - Its NOT null by default.
xmlDoc.LoadXml(xml);
Console.WriteLine(xmlDoc.InnerText);
Console.ReadLine();
}
Please go through below link for more information.
XML External Entity (XXE) Prevention Cheat Sheet
The original answer works for xmlDoc.Load(xmlreader).
The second question is a different context and requires different technology.
using (System.IO.StringReader rxml = new System.IO.StringReader(myxmltext))
{
XmlSerializer serializer = new XmlSerializer(typeof(MenuConfigBase));
using (XmlTextReader xr = new XmlTextReader(rxml))
{
xr.XmlResolver = null;
var cfgBase = (MenuConfigBase)serializer.Deserialize(xr);
}
}
I've read about all I could get on how to read from an XML file, but I can't get anything done. I want to read a connectionstring from an XML file, plain and simple, nothing more.
My XML looks like
<?xml version="1.0" standalone="yes"?>
<connectionString>
<conn>"adsf"</conn>
</connectionString>
And I've tried varios way with
XmlDocument doc = new XmlDocument();
XmlTextReader reader = new XmlTextReader(xmlLoc);
while (reader.MoveToNextAttribute())
{
XmlNode a = doc.ReadNode(reader);
textBox1.Text = Text + a.Name;
}
XmlDocument xml = new XmlDocument();
xml.LoadXml(xmlLoc); //myXmlString is the xml file in string //copying xml to string: string myXmlString = xmldoc.OuterXml.ToString();
XmlNodeList xnList = xml.SelectNodes("/connectionString");
foreach (XmlNode xn in xnList)
{
XmlNode example = xn.SelectSingleNode("conn");
if (example != null)
{
string na = example["Name"].InnerText;
string no = example["NO"].InnerText;
}
}
I'm missing something and I'm not sure what, this should be a very simple task, but I can't get it done. Any help?
I'm trying to do it in a WIndows form application program.
I'm missing something?
Yes. .NET has a built in mechanism for storing your connection string, inside an App.config file, there is no reason to manually store it and parse it yourself.
Right click your project, go to Add -> New Item
Then, add a "Application Configuration File":
Once it opens, add a connectionStrings node to it, as follows:
// This is an example of a connectionString node. You may add child
// values to it as follows
<connectionStrings>
<add name="YourConnectionStringKey"
providerName="System.Data.SqlClient"
connectionString="Data Source=.\SQLEXPRESS;Initial Catalog=YourDB;Trusted_Connection=Yes" />
</connectionStrings>
Then, you access it using ConfigurationManager.ConnectionStrings:
string connectionString =
ConfigurationManager.ConnectionStrings["YourConnectionStringKey"].ConnectionString;
You can use linq to xml.
var xmlStr = File.ReadAllText("fileName.xml");
var str = XElement.Parse(xmlStr);
var result = str.Elements("word").
Where(x => x.Element("connectionString").Value.Equals("conn"));
Console.WriteLine(result);
This might work (or may be some changes you need to make.
var x = XElement.Parse(#"<?xml version=""1.0"" standalone=""yes""?><connectionString><conn>adsf</conn></connectionString>");
// or var x = XElement.Load(#"c:\temp\my.xml");
var s = x.Element("conn").Value;
If you still have not found your answer then try this (a bit old school but it worked for me)
public class Common
{
public Common()
{
}
// public static string GetXML()
// {
// return #"C:\MyLocation\Connections.xml";
// }
public static string GetXMLconn(string strConn)
{
string xmlConStr = "";
//
string XMLconn = #"C:\Mylocation\Connections.xml";
// Get the Connection String from the XML file.
XmlTextReader textReader = new XmlTextReader(XMLconn);
textReader.Read();
while (textReader.Read())
{
// Read the currect element in the loop
textReader.MoveToElement();
// If the element name is correct then read and assign the connection string
if (textReader.Name == strConn)
{
xmlConStr = textReader.ReadString();
}
}
textReader.Close();
return xmlConStr;
}
}
I've got simple XML like:
<?xml version="1.0" encoding="utf-8"?>
<ftp>
<address>ftp://ftp.example.com/</address>
<user>jondoe</user>
<password>Password123</password>
</ftp>
And I wanted to use this C# code:
using (XmlReader reader = XmlReader.Create(xmlPath))
{
reader.ReadToFollowing("address");
string ftpAddress = reader.ReadElementContentAsString();
reader.ReadToFollowing("user");
string ftpUser = reader.ReadElementContentAsString();
reader.ReadToFollowing("password");
string ftpPw = reader.ReadElementContentAsString();
}
It's working fine when I want to read only one content, like address but it fails when I want to read more/next ones. I thought this would be logical but it seems like it's not. How to read that XML and all elements of it: address, user and password? I would like to use XmlReader for that.
The simplest form I can think of would be this one:
XElement xml = XElement.Parse(File.ReadAllText(xmlPath));
var ftpAddress = xml.Element("address").Value;
var ftpUser = xml.Element("user").Value;
var ftpPwd = xml.Element("user").Value;
Of course you should add some safety by checking for null values and if the file exists..
Update:
I would implement a failsafe version this way:
if (!File.Exists(xmlPath))
throw new FileNotFoundException(string.Format("The FTP configuration file {0} is missing", xmlPath));
XElement xml = XElement.Parse(File.ReadAllText(xmlPath));
var ftpAddress = GetConfigValue(xml, "address");
var ftpUser = GetConfigValue(xml, "user");
var ftpPwd = GetConfigValue(xml, "password");
With GetConfigValue like this:
private static string GetConfigValue(XContainer parent, XName name)
{
var element = parent.Element(name);
if (element == null)
throw new ArgumentException(string.Format("Invalid configuration file, missing element {0}", name));
return element.Value;
}
I didn't know that I can use XSD schema to serialize received XML file. I used xsd.exe to generate cs class from XSD file and now I need to use that class to get data in class properties but I miss one thing and I need help.
This is the code:
private void ParseDataFromXmlDocument_UsingSerializerClass(XmlDocument doc)
{
XmlSerializer ser = new XmlSerializer(typeof(ClassFromXsd));
string filename = Path.Combine("C:\\myxmls\\test", "xmlname.xml");
ClassFromXsdmyClass = ser.Deserialize(new FileStream(filename, FileMode.Open)) as ClassFromXsd;
if (myClass != null)
{
// to do
}
...
Here I use XML file from drive. And I want to use this XmlDocument from parameter that I passed in. So how to adapt this code to use doc instead XML from drive?
You could write the XmlDocument to a MemoryStream, and then Deserialize it like you already did.
XmlDocument doc = new XmlDocument();
ClassFromXsd obj = null;
using (var s = new MemoryStream())
{
doc.Save(s);
var ser = new XmlSerializer(typeof (ClassFromXsd));
s.Seek(0, SeekOrigin.Begin);
obj = (ClassFromXsd)ser.Deserialize(s);
}
Recently, I began developing an application that utilizes the use of XML documents in a C# program. Everything worked fine to begin with, but as I edited the code, and added a bit more features to the program in case the XML gets deleted, corrupted, etc, the program didn't want to function properly anymore.
The following code is used when submitting the data and transferring it to XML:
private void doneCreate_Click(object sender, EventArgs e)
{
//Initialize new XMLDocument class.
XmlDocument XmlDoc = new XmlDocument();
//See if the card data file is there, if not, create it.
if (File.Exists(xmlPath) == false)
{
using (FileStream createFile = File.Create(xmlPath))
{
Byte[] FileData = new UTF8Encoding(true).GetBytes(toBase64("<studycards></studycards>"));
// Add some information to the file.
createFile.Write(FileData, 0, FileData.Length);
createFile.Close();
}
XMLData = "<studycards></studycards>";
}
else
{
XMLData = readXML();
if (XMLData == "")
{
XMLData = "<studycards></studycards>";
}
else
{
XMLData = fromBase64(XMLData);
}
}
XmlDoc.LoadXml(XMLData);
XmlElement Group = XmlDoc.CreateElement("Group", null);
XmlAttribute Group_Attr = XmlDoc.CreateAttribute("Name");
Group_Attr.Value = groupName.Text;
Group.Attributes.Append(Group_Attr);
foreach (string[] Card in CardData)
{
try
{
FrontData = Card[0].ToString();
BackData = Card[1].ToString();
NewCard = XmlDoc.CreateElement("Card");
FrontElement = XmlDoc.CreateElement("Front");
FrontElement.InnerText = FrontData;
BackElement = XmlDoc.CreateElement("Back");
BackElement.InnerText = BackData;
NewCard.AppendChild(FrontElement);
NewCard.AppendChild(BackElement);
Group.AppendChild(NewCard);
}
catch
{
break;
}
}
XmlDoc.DocumentElement.AppendChild(Group);
XmlTextWriter write = new XmlTextWriter(xmlPath, null);
write.Formatting = Formatting.Indented;
XmlDoc.Save(write);
}
Upon attempting to click "Done" in the application, I'm presented with the following Exception:
The process cannot access the file 'C:\Users\Toshiba\documents\visual studio 2010\Projects\StudyCards\StudyCards\bin\Debug\Resources\card_data.xml' because it is being used by another process.
Any solutions?
This may well be at least part of the problem:
XmlTextWriter write = new XmlTextWriter(xmlPath, null);
write.Formatting = Formatting.Indented;
XmlDoc.Save(write);
You're never closing the writer, so I would expect it to keep the file open. That will stop future attempts to open the file, until the finalizer kicks in.
Alternatively it could be part of readXML(), which you haven't shown - again, if that leaves the file open, that would cause problems.