简体   繁体   中英

Read then write html to xml file using linq xml and xml writer

I am reading the Value of a element <content>Text with <br /> break</content> into a string and showing that string in a TextBox . Afterwards the user can modify it possibly with additional HTML tags. Upon using linq to query the exact node to insert the user-input all spiky bracket <> from html tags are normalized into &lt;br /&gt; . So how do I preseve my html tags?

I already read and tried the solutions from these questions but I failed to apply it to my use case: c# XML avoid html encode using XDocument

Get html tags embedded in xml using linq

Keep HTML tags in XML using LINQ to XML

http://blogs.msdn.com/b/charlie/archive/2008/09/29/linq-farm-preserving-formats-with-linq-to-xml.aspx

This is an example of my xml file:

<events>
    <event id="0">
        <content><br/></content>
    </event>
</events>

How I load and query:

XDocument xml;
XmlTextReader xtr = new XmlTextReader(this.pathXML);

xtr.Normalization = false;
xml = XDocument.Load(xtr, LoadOptions.PreserveWhitespace);
xtr.Close();

var nodeToEdit = xml.Descendants("event").Where(x => (string)x.Attribute("id") == "0");

How I manipulate my xml file with user input:

string userinput = "Text with <br /> break"; // This is read from TextBox control inside Form
foreach (var item in nodeToEdit.Elements())
{
    if(item.Name == "content")
    {
        item.Value = userinput;
    }
}

How I save:

changeSaveIndent(xml, this.pathXML);
public static void changeSaveIndent(XDocument x, string path)
{
    XmlWriterSettings settings = new XmlWriterSettings();
    settings.Indent = true;
    // Indent by tab. Can be changed to "    " or similar
    settings.IndentChars = "\t";

    using (XmlWriter writer = XmlTextWriter.Create(path, settings))
    {
        x.Save(writer);
    }
}

My expected xml output file should look like this:

<events>
    <event id="0">
        <content>Text with <br /> break</content>
    </event>
</events>

sorry for the long post..

Replace this:

if(item.Name == "content")
{
    item.Value = userinput;
}

with this:

if(item.Name == "content")
{
    item.ReplaceWith(XElement.Parse("<content>" + userinput + "</content>"));
}

Just note that your user input will have to be valid XML for this to work. If not, you'd probably be best off breaking out the call to XElement.Parse into a try catch block or just adding the input as unescaped CDATA, like so:

if (item.Name == "content")
{
    item.Value = "";
    item.Add(new XCData(userinput));
}

Which would produce XML that looks like this:

...
<content><![CDATA[Text with <br /> break]]></content>
...

Based on what you are describing, I would say that you are using the wrong format in your XML file. <br/> isn't describing a new node in the XML file at all, you are using it as part of content, and therefore it should be encoded. But that said, if you must retrieve and set the content node like you describe, you want .InnerXml , not .Value or .Text or .InnerText

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM