0

I've got to create a file with xml header and after that i have to put normal data, smthing like this:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Header>
  <Algorithm>alg</Algorithm>
  <nod2>aaa</nod2>
  <nod3>bbb</nod3>      
  <node>
    <User>
     <Email />
     <SessionKey />
     </User>
  </node>
</Header>
Data of the file....

I've already got the code to write it to the file.

Code for that part:

private void setHeader(FileStream output, string nod2, string nod3, string )
{            
    XmlDocument doc = new XmlDocument();
    XmlNode docNode = doc.CreateXmlDeclaration("1.0", "UTF-8", "yes");
    doc.AppendChild(docNode);

    XmlNode header = doc.CreateElement("Header");
    doc.AppendChild(header);

    XmlNode algorithm = doc.CreateElement("Algorithm");
    algorithm.InnerText = "alg";
    header.AppendChild(algorithm);
    XmlNode node2= doc.CreateElement("nod2");
    node2.InnerText = nod2;
    header.AppendChild(node2);
    XmlNode node3= doc.CreateElement("nod3");
    node3.InnerText = nod3;
    header.AppendChild(node3);

    XmlNode node= doc.CreateElement("node");
    header.AppendChild(node);

    XmlNode user1 = doc.CreateElement("User");
    node.AppendChild(user1);

    XmlNode mail = doc.CreateElement("Email");
    user1.AppendChild(mail);
    XmlNode sessionKey = doc.CreateElement("SessionKey");
    user1.AppendChild(sessionKey);

    doc.Save(output);            
}

It work's pretty well, but when i want to read it with

private void readHeader(FileStream input, out string algorithm)
{
    XmlDocument doc = new XmlDocument();
    doc.Load(input);
}

I got an error that when the "Data of the file..." starts: "Data on the root level is invalid". Is there a way to do it with the data after whole xml, or have i to add the data as a node?

Gutts
  • 13
  • 3
  • 1
    *"It work's pretty well"* -- how do you know? It doesn't even compile. Please show us your *actual* code. If your example "XML" at the top of your question is what you're really generating, it's not valid XML. – 15ee8f99-57ff-4f92-890c-b56153 May 18 '18 at 13:51
  • I'm using it for my program which encrypts and decrypts files. The xml part should describe encryption settings, after it comes the encrypted data of orginal file and it's not inside any node. So when i generate file and open it with notepad it looks just as what i'm asked to do, like the xml at the top. Is the data outside the node invalid? If yes, is there a easy way to read just a header which is valid xml and ignore data that is not in node? – Gutts May 18 '18 at 14:56
  • *"it's not inside any node*" -- if so, you can't parse the file with an XML parser. You've got two options: 1. Parse the header separately; 2: put the data in a CDATA block in the XML itself: `
    ...
    <![CDATA[ ... ]]>
    `. I think you'd Base64 encode the encrypted data.
    – 15ee8f99-57ff-4f92-890c-b56153 May 18 '18 at 15:01
  • Yes, [you'll need to encode the encrypted data](https://stackoverflow.com/a/17485642/424129) in the CDATA block. That's by far the preferred approach. – 15ee8f99-57ff-4f92-890c-b56153 May 18 '18 at 15:06
  • I'd also prefer to put it inside a node, but I'm asked to do it otherway :/ Thanks for help :) – Gutts May 18 '18 at 15:09
  • If it's absolutely required to do it "wrong", read the file as a string, search for `""`, and split up the data at the end of that substring. Pass only the XML part to the parser. Ugly but workable. – 15ee8f99-57ff-4f92-890c-b56153 May 18 '18 at 15:11

3 Answers3

0

I tested your code with writing directly to a file, doc.Save(@"c:\temp\test1.xml"); And loading from that file works fine. So there is nothing wrong with your xml document. Check your FileStream. Do you flush and close it properly? Does it have UTF-8 encoding? What's the input in the node strings. Nothing that is invalid according to xml rules?

  • I'm using it for my program which encrypts and decrypts files. The xml part should describe encryption settings, after it comes the encrypted data of orginal file and it's not inside any node. So when i generate file and open it with notepad it looks just as what i'm asked to do, like the xml at the top. Is the data outside the node invalid? If yes, is there a easy way to read just a header which is valid xml and ignore data that is not in node? – Gutts May 18 '18 at 14:59
0

This can be done in multiple ways. In comments, you've indicated that the best way is unacceptable for reasons outside the scope of the discussion. For completeness, I'm going to put that one first anyway. Skip down to tl;dr for what I think you'll have to end up doing.

The preferred way to do this is to base64 encode the encrypted data and put it in a CDATA block:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<File>
    <Header>
      <Algorithm>alg</Algorithm>
      <nod2>aaa</nod2>
      <nod3>bbb</nod3>      
      <node>
        <User>
         <Email />
         <SessionKey />
         </User>
      </node>
    </Header>
    <Data><![CDATA[
    ICAgIFhtbE5vZGUgYWxnb3JpdGhtID0gZG9jLkNyZWF0ZUVsZW1lbnQoIkFsZ29yaXRobSIpOw0K
    ICAgIGFsZ29yaXRobS5Jbm5lclRleHQgPSAiYWxnIjsNCiAgICBoZWFkZXIuQXBwZW5kQ2hpbGQo
    YWxnb3JpdGhtKTsNCiAgICBYbWxOb2RlIG5vZGUyPSBkb2MuQ3JlYXRlRWxlbWVudCgibm9kMiIp
    Ow0KICAgIG5vZGUyLklubmVyVGV4dCA9IG5vZDI7DQogICAgaGVhZGVyLkFwcGVuZENoaWxkKG5v
    ZGUyKTsNCiAgICBYbWxOb2RlIG5vZGUzPSBkb2MuQ3JlYXRlRWxlbWVudCgibm9kMyIpOw0KICAg
    IG5vZGUzLklubmVyVGV4dCA9IG5vZDM7DQogICAgaGVhZGVyLkFwcGVuZENoaWxkKG5vZGUzKTs=
    ]]></Data>
</File>

That's the canonical answer to this question.

But you've told me that in your case, a requirement has been imposed that you can't do it that way.

Second choice is MIME (actually, MIME might be the first choice and the above might be the second). But I have a feeling they won't like MIME either.

Third choice, read the file as a string and search for some marker that's inserted between the XML and the binary data, something like a MIME boundary.

tl;dr

If they won't let you add such a marker to the file (and I bet they won't), search for the first occurrence of the substring "</Header>":

var xml = File.ReadAllText(filePath);
var endTag = "</Header>";

var headerXML = xml.Substring(0, xml.IndexOf(endTag) + endTag.Length);

var xdHeader = new XmlDocument();
xdHeader.LoadXml(headerXML);
Community
  • 1
  • 1
0

After a single root node, only comments and processor instructions can be written to xml. So, you can try to write your data in the comments.

It will look like this:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Header>
  ...
</Header>
<!-- your data -->
<!-- another data -->

This method has limitations: your data may not contain -- (double-hyphen) and may not end in -.

But it is better, of course, not to do so.

Alexander Petrov
  • 13,457
  • 2
  • 20
  • 49