简体   繁体   中英

Edit CustomXML with OpenXML C#

This is my first OpenXML project. I am trying to edit the CustomXML file of a docx file. I am trying to change this:

      <?xml version="1.0" encoding="UTF-8"?>
      <PERSON>
          <NAMETAG>NAME</NAMETAG>
          <DOBTAG>DOB</DOBTAG>
          <SCORE1TAG>SCORE1</SCORE1TAG>
          <SCORE2TAG>SCORE2</SCORE2TAG>
      </PERSON>

To this:

      <?xml version="1.0" encoding="UTF-8"?>
      <PERSON>
          <NAMETAG>John Doe</NAMETAG>
          <DOBTAG>01/01/2020</DOBTAG>
          <SCORE1TAG>90.5</SCORE1TAG>
          <SCORE2TAG>100.0</SCORE2TAG>
      </PERSON>

I would prefer to not use search and replace but instead navigate the WordprocessingDocument to find the correct properties to modify. I tried to do a whole delete/add but that corrupted the file and did not work. Here is that code:

static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");

            byte[] byteArray = File.ReadAllBytes(@"C:\Simple_Template.docx");

            using (MemoryStream stream = new MemoryStream())
            {
                stream.Write(byteArray, 0, (int)byteArray.Length);
                WordprocessingDocument doc = WordprocessingDocument.Open(stream, true);

                doc.MainDocumentPart.DeleteParts<CustomXmlPart>(doc.MainDocumentPart.CustomXmlParts);

                string newcustomXML = @"<?xml version=""1.0\"" encoding=""UTF-8\""?><Person><NAMETAG>John Doe</NAMETAG><DOBTAG>DOB</DOBTAG><SCORE1TAG>90.5</SCORE1TAG><SCORE2TAG>100.0</SCORE2TAG></PERSON>";

                CustomXmlPart xmlPart = doc.MainDocumentPart.AddCustomXmlPart(CustomXmlPartType.CustomXml);
                byte[] byteArrayXML = Encoding.UTF8.GetBytes(newcustomXML);
                using (MemoryStream xml_strm = new MemoryStream(byteArrayXML))
                {
                    xmlPart.FeedData(xml_strm);
                }


                doc.MainDocumentPart.Document.Save();
                doc.Close();

                File.WriteAllBytes(@"C:\Simple_Template_Replace.docx", stream.ToArray());
            }
        }

I have also tried to navigate through the structure but I am having a hard time figuring out where in the WordprocessingDocument object contains the actual values that I need to modify. Ideally, I would like something like this psuedo-code:

doc.MainDocumentPart.CustomXMLPart.Select("NAMETAG") = "John Doe"

--------Follow On----------

The answer below worked well without a Namespace. Now I would like to add one. This is the new XML:

<?xml version="1.0"?><myxml xmlns="www.mydomain.com">
<PERSON>
  <NAMETAG>NAME</NAMETAG>
  <DOBTAG>DOB</DOBTAG>
  <SCORE1TAG>SCORE1</SCORE1TAG>
  <SCORE2TAG>SCORE2</SCORE2TAG>
</PERSON>
</myxml>

I have adjusted the code to the following but the SelectSingleNode call is returning NULL. Here is the updated code:

                    XmlNamespaceManager mgr = new XmlNamespaceManager(xmlDocument.NameTable);
                    mgr.AddNamespace("ns", "www.mydomain.com");

                    string name_tag = xmlDocument.SelectSingleNode("/ns:myxml/ns:PERSON/ns:NAMETAG", mgr).InnerText;

I was able to fix this myself. I did not realize that you need to include "ns:" with every element. I still thought that I would be able to pass in String.Empty into my AddNamespace and then I would not have to do it. But this will work for now.

The problem is with the newcustomXML value, it has two '\' characters in the XML declaration and also the start tag of "PERSON" element has capital case instead of upper case.

So, try using the following instead:

string newcustomXML = @"<?xml version=""1.0"" encoding=""UTF-8""?>
<PERSON>
    <NAMETAG>John Doe</NAMETAG>
    <DOBTAG>01/01/2020</DOBTAG>
    <SCORE1TAG>90.5</SCORE1TAG>
    <SCORE2TAG>100.0</SCORE2TAG>
</PERSON>";

Also regarding your navigation attempt, try using this:

static void Main(string[] args)
{
    Console.WriteLine("Hello World!");

    byte[] byteArray = File.ReadAllBytes(@"C:\Simple_Template.docx");
    using (MemoryStream stream = new MemoryStream())
    {
        stream.Write(byteArray, 0, (int)byteArray.Length);
        WordprocessingDocument doc = WordprocessingDocument.Open(stream, true);

        CustomXmlPart xmlPart = doc.MainDocumentPart.CustomXmlParts.First();
        XmlDocument xmlDocument = new XmlDocument();

        using (var inputStream = xmlPart.GetStream(FileMode.Open, FileAccess.Read))
        using (var outputStream = new MemoryStream())
        {
            xmlDocument.Load(inputStream);
            xmlDocument.SelectSingleNode("/PERSON/NAMETAG").InnerText = "John Doe";

            xmlDocument.Save(outputStream);
            outputStream.Seek(0, SeekOrigin.Begin);
            xmlPart.FeedData(outputStream);
        }

        doc.MainDocumentPart.Document.Save();
        doc.Close();

        File.WriteAllBytes(@"C:\Simple_Template_Replace.docx", stream.ToArray());
    }
}

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