4

I’m trying to merge multiple Word (.docx) documents using OpenXML in C#. The merge itself works, but I’m having a persistent issue with numbered and bulleted lists.

Problem

When I copy paragraphs and their <w:numPr> references from the source document into the target, the numbering from different documents does not stay separate:

  • If the first document has bullets and the second has numbers → all lists in the merged file become numbers.
  • If the first document has numbers and the second has bullets → all lists in the merged file become bullets.
  • If both have numbers, instead of restarting at 1, the numbering continues (e.g., doc1 ends at 4, doc2 starts at 5).

It seems that whichever list type is last added to numbering.xml in the target document overwrites the previous ones.

What I Tried

  • Creating new <w:abstractNum> and <w:num> entries for each source document.
  • Generating new nsid and name attributes per list to avoid collisions.
  • Tracking mappings with dictionaries for numId and abstractNumId.
  • Ensuring startOverride is set to 1 for each level.

In essence, this is the code I am calling and all the magic is happening in NumberHelper.MyCodeHelper(). I would like to avoid posting all that code and just give my XML output for each source and the numbering.xml of the target document and maybe someone will be able to tell me where I am going wrong because as I understand it, the XML doesn't look to have any glaring ID issues.

  var targetDoc = targetWml
        NumberHelper.ResetGlobalMaps();
        foreach (var sourceDoc in sourceDocs)
        {
        var result = NumberHelper.MyCodeHelper(WordprocessingDocument sourceDoc, WmlDocument targetDoc);
        targetDoc = result.UpdatedDoc;
        updatedParagraphs = result.UpdatedParagraphs;
        
        //I then have some code here that I am using to insert the result.UpdatedPargraphs into the targetDoc. This code is not having any issues. It is a numbering.xml issue, I am almost certain.
        
        }
    

Source1 XML that I am inserting and Image of its appearance in document.

![enter image description here

<w:body xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"><w:p xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
  <w:pPr>
    <w:numPr>
      <w:ilvl w:val="0" />
      <w:numId w:val="1" />
    </w:numPr>
    <w:spacing w:before="0" w:after="0" w:afterAutospacing="0" w:line="240" />
    <w:rPr />
  </w:pPr>
  <w:r>
    <w:rPr>
      <w:rFonts w:ascii="Times New Roman" />
      <w:sz w:val="24" />
    </w:rPr>
    <w:t xml:space="preserve">This is atest</w:t>
  </w:r>
</w:p>
<w:p xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
  <w:pPr>
    <w:numPr>
      <w:ilvl w:val="0" />
      <w:numId w:val="1" />
    </w:numPr>
    <w:spacing w:before="0" w:after="0" w:afterAutospacing="0" w:line="240" />
    <w:rPr />
    <w:ind w:right="0" />
  </w:pPr>
  <w:r>
    <w:rPr>
      <w:rFonts w:ascii="Times New Roman" />
      <w:sz w:val="24" />
    </w:rPr>
    <w:t xml:space="preserve">asdfads</w:t>
  </w:r>
</w:p>
<w:p xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
  <w:pPr>
    <w:numPr>
      <w:ilvl w:val="0" />
      <w:numId w:val="1" />
    </w:numPr>
    <w:spacing w:before="0" w:after="0" w:afterAutospacing="0" w:line="240" />
    <w:rPr />
    <w:ind w:right="0" />
  </w:pPr>
  <w:r>
    <w:rPr>
      <w:rFonts w:ascii="Times New Roman" />
      <w:sz w:val="24" />
    </w:rPr>
    <w:t xml:space="preserve">fasdfasdfad</w:t>
  </w:r>
</w:p>
<w:p xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
  <w:pPr>
    <w:numPr>
      <w:ilvl w:val="0" />
      <w:numId w:val="1" />
    </w:numPr>
    <w:spacing w:before="0" w:after="0" w:afterAutospacing="0" w:line="240" />
    <w:rPr />
    <w:ind w:right="0" />
  </w:pPr>
  <w:r>
    <w:rPr>
      <w:rFonts w:ascii="Times New Roman" />
      <w:sz w:val="24" />
    </w:rPr>
    <w:t xml:space="preserve">fasdfads</w:t>
  </w:r>
</w:p>
<w:p xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
  <w:pPr>
    <w:numPr>
      <w:ilvl w:val="1" />
      <w:numId w:val="1" />
    </w:numPr>
    <w:spacing w:before="0" w:after="0" w:afterAutospacing="0" w:line="240" />
    <w:rPr />
    <w:ind w:right="0" />
  </w:pPr>
  <w:r>
    <w:rPr>
      <w:rFonts w:ascii="Times New Roman" />
      <w:sz w:val="24" />
    </w:rPr>
    <w:t xml:space="preserve">asdfasdf</w:t>
  </w:r>
</w:p>
<w:p xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
  <w:pPr>
    <w:numPr>
      <w:ilvl w:val="1" />
      <w:numId w:val="1" />
    </w:numPr>
    <w:spacing w:before="0" w:after="0" w:afterAutospacing="0" w:line="240" />
    <w:rPr />
    <w:ind w:right="0" />
  </w:pPr>
  <w:r>
    <w:rPr>
      <w:rFonts w:ascii="Times New Roman" />
      <w:sz w:val="24" />
    </w:rPr>
    <w:t xml:space="preserve">asdfasdfsdf</w:t>
  </w:r>
</w:p>
<w:p xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
  <w:pPr>
    <w:numPr>
      <w:ilvl w:val="1" />
      <w:numId w:val="1" />
    </w:numPr>
    <w:spacing w:before="0" w:after="0" w:afterAutospacing="0" w:line="240" />
    <w:rPr />
    <w:ind w:right="0" />
  </w:pPr>
  <w:r>
    <w:rPr>
      <w:rFonts w:ascii="Times New Roman" />
      <w:sz w:val="24" />
    </w:rPr>
    <w:t xml:space="preserve">asdfdsaf</w:t>
  </w:r>
</w:p>
<w:p xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
  <w:pPr>
    <w:numPr>
      <w:ilvl w:val="2" />
      <w:numId w:val="1" />
    </w:numPr>
    <w:spacing w:before="0" w:after="0" w:afterAutospacing="0" w:line="240" />
    <w:rPr />
    <w:ind w:right="0" />
  </w:pPr>
  <w:r>
    <w:rPr>
      <w:rFonts w:ascii="Times New Roman" />
      <w:sz w:val="24" />
    </w:rPr>
    <w:t xml:space="preserve">adsfasdfasdf</w:t>
  </w:r>
</w:p>
<w:p xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
  <w:pPr>
    <w:numPr>
      <w:ilvl w:val="1" />
      <w:numId w:val="1" />
    </w:numPr>
    <w:spacing w:before="0" w:after="0" w:afterAutospacing="0" w:line="240" />
    <w:rPr />
    <w:ind w:right="0" />
  </w:pPr>
  <w:r>
    <w:rPr>
      <w:rFonts w:ascii="Times New Roman" />
      <w:sz w:val="24" />
    </w:rPr>
    <w:t xml:space="preserve">asdfasdfasdf</w:t>
  </w:r>
</w:p>
<w:p xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
  <w:pPr>
    <w:numPr>
      <w:ilvl w:val="0" />
      <w:numId w:val="1" />
    </w:numPr>
    <w:spacing w:before="0" w:after="0" w:afterAutospacing="0" w:line="240" />
    <w:rPr />
    <w:ind w:right="0" />
  </w:pPr>
  <w:r>
    <w:rPr>
      <w:rFonts w:ascii="Times New Roman" />
      <w:sz w:val="24" />
    </w:rPr>
    <w:t xml:space="preserve">asdfadsfasdfdsafasdf</w:t>
  </w:r>
</w:p></w:body>

Source2 XML that I am inserting and Image of its appearance in document.

enter image description here

<w:body xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"><w:p xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
  <w:pPr>
    <w:numPr>
      <w:ilvl w:val="0" />
      <w:numId w:val="2" />
    </w:numPr>
    <w:spacing w:before="0" w:after="0" w:afterAutospacing="0" w:line="240" />
    <w:rPr />
  </w:pPr>
  <w:r>
    <w:rPr>
      <w:rFonts w:ascii="Times New Roman" />
      <w:sz w:val="24" />
    </w:rPr>
    <w:t xml:space="preserve">This iadfasdf adf</w:t>
  </w:r>
</w:p>
<w:p xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
  <w:pPr>
    <w:numPr>
      <w:ilvl w:val="0" />
      <w:numId w:val="2" />
    </w:numPr>
    <w:spacing w:before="0" w:after="0" w:afterAutospacing="0" w:line="240" />
    <w:rPr />
    <w:ind w:right="0" />
  </w:pPr>
  <w:r>
    <w:rPr>
      <w:rFonts w:ascii="Times New Roman" />
      <w:sz w:val="24" />
    </w:rPr>
    <w:t xml:space="preserve">asdfasd</w:t>
  </w:r>
</w:p>
<w:p xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
  <w:pPr>
    <w:numPr>
      <w:ilvl w:val="0" />
      <w:numId w:val="2" />
    </w:numPr>
    <w:spacing w:before="0" w:after="0" w:afterAutospacing="0" w:line="240" />
    <w:rPr />
    <w:ind w:right="0" />
  </w:pPr>
  <w:r>
    <w:rPr>
      <w:rFonts w:ascii="Times New Roman" />
      <w:sz w:val="24" />
    </w:rPr>
    <w:t xml:space="preserve">fasdfasdf</w:t>
  </w:r>
</w:p>
<w:p xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
  <w:pPr>
    <w:numPr>
      <w:ilvl w:val="1" />
      <w:numId w:val="2" />
    </w:numPr>
    <w:spacing w:before="0" w:after="0" w:afterAutospacing="0" w:line="240" />
    <w:rPr />
    <w:ind w:right="0" />
  </w:pPr>
  <w:r>
    <w:rPr>
      <w:rFonts w:ascii="Times New Roman" />
      <w:sz w:val="24" />
    </w:rPr>
    <w:t xml:space="preserve">asdfasdfasd</w:t>
  </w:r>
</w:p>
<w:p xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
  <w:pPr>
    <w:numPr>
      <w:ilvl w:val="1" />
      <w:numId w:val="2" />
    </w:numPr>
    <w:spacing w:before="0" w:after="0" w:afterAutospacing="0" w:line="240" />
    <w:rPr />
    <w:ind w:right="0" />
  </w:pPr>
  <w:r>
    <w:rPr>
      <w:rFonts w:ascii="Times New Roman" />
      <w:sz w:val="24" />
    </w:rPr>
    <w:t xml:space="preserve">fasdfasd</w:t>
  </w:r>
</w:p>
<w:p xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
  <w:pPr>
    <w:numPr>
      <w:ilvl w:val="1" />
      <w:numId w:val="2" />
    </w:numPr>
    <w:spacing w:before="0" w:after="0" w:afterAutospacing="0" w:line="240" />
    <w:rPr />
    <w:ind w:right="0" />
  </w:pPr>
  <w:r>
    <w:rPr>
      <w:rFonts w:ascii="Times New Roman" />
      <w:sz w:val="24" />
    </w:rPr>
    <w:t xml:space="preserve">fadsafs</w:t>
  </w:r>
</w:p>
<w:p xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
  <w:pPr>
    <w:numPr>
      <w:ilvl w:val="2" />
      <w:numId w:val="2" />
    </w:numPr>
    <w:spacing w:before="0" w:after="0" w:afterAutospacing="0" w:line="240" />
    <w:rPr />
    <w:ind w:right="0" />
  </w:pPr>
  <w:r>
    <w:rPr>
      <w:rFonts w:ascii="Times New Roman" />
      <w:sz w:val="24" />
    </w:rPr>
    <w:t xml:space="preserve">adsfasdfasd</w:t>
  </w:r>
</w:p>
<w:p xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
  <w:pPr>
    <w:numPr>
      <w:ilvl w:val="0" />
      <w:numId w:val="2" />
    </w:numPr>
    <w:spacing w:before="0" w:after="0" w:afterAutospacing="0" w:line="240" />
    <w:rPr />
    <w:ind w:right="0" />
  </w:pPr>
  <w:r>
    <w:rPr>
      <w:rFonts w:ascii="Times New Roman" />
      <w:sz w:val="24" />
    </w:rPr>
    <w:t xml:space="preserve">asdfa</w:t>
  </w:r>
</w:p>
<w:p xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
  <w:pPr>
    <w:numPr>
      <w:ilvl w:val="0" />
      <w:numId w:val="2" />
    </w:numPr>
    <w:spacing w:before="0" w:after="0" w:afterAutospacing="0" w:line="240" />
    <w:rPr />
    <w:ind w:right="0" />
  </w:pPr>
  <w:r>
    <w:rPr>
      <w:rFonts w:ascii="Times New Roman" />
      <w:sz w:val="24" />
    </w:rPr>
    <w:t xml:space="preserve">sdfasdfadsf</w:t>
  </w:r>
</w:p>
<w:p xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
  <w:pPr>
    <w:numPr>
      <w:ilvl w:val="0" />
      <w:numId w:val="2" />
    </w:numPr>
    <w:spacing w:before="0" w:after="0" w:afterAutospacing="0" w:line="240" />
    <w:rPr />
    <w:ind w:right="0" />
  </w:pPr>
  <w:r>
    <w:rPr>
      <w:rFonts w:ascii="Times New Roman" />
      <w:sz w:val="24" />
    </w:rPr>
    <w:t xml:space="preserve">asdfsdf</w:t>
  </w:r>
</w:p></w:body>

Results - How it appears in the final document. EDIT: Removed final doc XML to post Code below:

enter image description here

EDIT:

Here is my Helper code that can be ran if you pass in the parameters you see. I have to remove the XML output that I am getting in order to post this.

public static class NumberingHelper
        {
        // Maps (docId, srcAbsId, signature) → mapped abstractNumId
        private static readonly Dictionary<((string docId, int srcAbsId), string absSignature), int> GlobalAbstractNumIdMap
            = new Dictionary<((string, int), string), int>();

        // Maps (docId, srcNumId, signature) → mapped numId
        private static readonly Dictionary<(string docId, int srcNumId, string absSignature), int> GlobalNumIdMap
            = new Dictionary<(string, int, string), int>();

        // Maps srcNumId → absSignature (per document, temporary)
        private static readonly Dictionary<int, string> SrcNumToAbsSignature
            = new Dictionary<int, string>();

        private static int maxAbsNumId = 0;
        private static int maxNumId = 0;

        public static void ResetGlobalMaps()
        {
            GlobalAbstractNumIdMap.Clear();
            GlobalNumIdMap.Clear();
            SrcNumToAbsSignature.Clear();
        }

        public static NumberingResult CopyNumberingAndParagraphs(
WordprocessingDocument sourceDoc,
WmlDocument targetWml)
        {
            XNamespace w = "http://schemas.openxmlformats.org/wordprocessingml/2006/main";
            //XNamespace w = "";

            byte[] targetBytes = targetWml.DocumentByteArray;

            // 1) Load source numbering
            XDocument sourceNumbering = null;
            if (sourceDoc?.MainDocumentPart?.NumberingDefinitionsPart != null)
            {
                using (var reader = new StreamReader(sourceDoc.MainDocumentPart.NumberingDefinitionsPart.GetStream()))
                {
                    sourceNumbering = XDocument.Load(reader);
                }
            }

            if (sourceNumbering == null)
                return new NumberingResult { UpdatedDoc = targetWml, UpdatedParagraphs = new List<XElement>() };

            // 2) Load target numbering (or create new)
            XDocument targetNumbering;
            using (var msLoad = new MemoryStream(targetBytes))
            using (var wDocLoad = WordprocessingDocument.Open(msLoad, false))
            {
                var mainPart = wDocLoad.MainDocumentPart;
                var numberingPart = mainPart.NumberingDefinitionsPart;
                if (numberingPart != null)
                {
                    using (var reader = new StreamReader(numberingPart.GetStream()))
                        targetNumbering = XDocument.Load(reader);
                }
                else
                {
                    targetNumbering = new XDocument(
                        new XElement(w + "numbering",
                            new XAttribute(XNamespace.Xmlns + "w", w.NamespaceName)));
                }
            }

            // 3) Determine max IDs in target numbering
            int maxAbsNumId = targetNumbering.Descendants(w + "abstractNum")
                .Select(a => (int?)a.Attribute(w + "abstractNumId"))
                .DefaultIfEmpty(0)
                .Max() ?? 0;

            int maxNumId = targetNumbering.Descendants(w + "num")
                .Select(n => (int?)n.Attribute(w + "numId"))
                .DefaultIfEmpty(0)
                .Max() ?? 0;

            // Unique prefix for this source doc instance
            string docGuid = (sourceDoc?.PackageProperties?.Identifier) ?? Guid.NewGuid().ToString("N");

            var srcNumToAbsSignature = new Dictionary<int, string>();

            // 4) Copy <num> elements from source
            foreach (var srcNum in sourceNumbering.Descendants(w + "num"))
            {
                var numAttr = srcNum.Attribute(w + "numId");
                if (numAttr == null || !int.TryParse(numAttr.Value, out int srcNumId))
                    continue;

                var absElem = srcNum.Element(w + "abstractNumId");
                if (absElem == null)
                    continue;

                var absAttr = absElem.Attribute(w + "val");
                if (absAttr == null || !int.TryParse(absAttr.Value, out int srcAbsId))
                    continue;

                var srcAbs = sourceNumbering.Descendants(w + "abstractNum")
                    .FirstOrDefault(a =>
                    {
                        var aAttr = a.Attribute(w + "abstractNumId");
                        return aAttr != null &&
                               int.TryParse(aAttr.Value, out int v) &&
                               v == srcAbsId;
                    });

                if (srcAbs == null)
                    continue;

                // Build unique signature
                string absSignature = string.Join("|",
                    new[] {
            (string)srcAbs.Element(w + "multiLevelType")?.Attribute(w + "val") ?? "",
            (string)srcAbs.Element(w + "nsid")?.Attribute(w + "val") ?? ""
                    }
                    .Concat(
                        srcAbs.Elements(w + "lvl").Select(l =>
                            $"{(int?)l.Attribute(w + "ilvl") ?? -1}-" +
                            $"{(string)l.Element(w + "numFmt")?.Attribute(w + "val") ?? ""}-" +
                            $"{(string)l.Element(w + "lvlText")?.Attribute(w + "val") ?? ""}-" +
                            $"{(string)l.Element(w + "lvlJc")?.Attribute(w + "val") ?? ""}-" +
                            $"{(string)l.Element(w + "isLgl")?.Attribute(w + "val") ?? ""}"
                        )
                    )
                );

                var absKey = ((docGuid, srcAbsId), absSignature + "|" + docGuid);

                if (!GlobalAbstractNumIdMap.TryGetValue(absKey, out int mappedAbsId))
                {
                    var clonedAbs = new XElement(srcAbs);

                    mappedAbsId = ++maxAbsNumId;
                    clonedAbs.SetAttributeValue(w + "abstractNumId", mappedAbsId);

                    // generate fresh nsid
                    var newNsid = Guid.NewGuid().ToString("N").Substring(0, 8).ToUpperInvariant();
                    var nsidElem = clonedAbs.Element(w + "nsid");
                    if (nsidElem != null) nsidElem.SetAttributeValue(w + "val", newNsid);
                    else clonedAbs.Add(new XElement(w + "nsid", new XAttribute(w + "val", newNsid)));

                    // give it its own name
                    var nameElem = clonedAbs.Element(w + "name");
                    if (nameElem != null) nameElem.SetAttributeValue(w + "val", $"List_{newNsid}");
                    else clonedAbs.Add(new XElement(w + "name", new XAttribute(w + "val", $"List_{newNsid}")));

                    // ensure multiLevelType is preserved
                    var multiElem = srcAbs.Element(w + "multiLevelType");
                    if (multiElem != null)
                        clonedAbs.Add(new XElement(w + "multiLevelType",
                            new XAttribute(w + "val", multiElem.Attribute(w + "val")?.Value)));

                    targetNumbering.Root.Add(clonedAbs);
                    GlobalAbstractNumIdMap[absKey] = mappedAbsId;
                }

                int newNumForThis = ++maxNumId;
                GlobalNumIdMap[(docGuid, srcNumId, absSignature)] = newNumForThis;
                srcNumToAbsSignature[srcNumId] = absSignature;

                var clonedNum = new XElement(srcNum);
                clonedNum.SetAttributeValue(w + "numId", newNumForThis);

                var absRefElem = clonedNum.Element(w + "abstractNumId");
                if (absRefElem != null)
                    absRefElem.SetAttributeValue(w + "val", mappedAbsId);
                else
                    clonedNum.Add(new XElement(w + "abstractNumId",
                        new XAttribute(w + "val", mappedAbsId)));

                // Add lvlOverride resets
                var mappedAbsElem = targetNumbering
                    .Descendants(w + "abstractNum")
                    .First(a => (int)a.Attribute(w + "abstractNumId") == mappedAbsId);

                var ilvls = mappedAbsElem
                    .Elements(w + "lvl")
                    .Select(l => (int)l.Attribute(w + "ilvl"))
                    .ToList();

                foreach (var i in ilvls)
                {
                    var lo = clonedNum.Elements(w + "lvlOverride")
                                      .FirstOrDefault(x => (int?)x.Attribute(w + "ilvl") == i);
                    if (lo == null)
                    {
                        lo = new XElement(w + "lvlOverride", new XAttribute(w + "ilvl", i));
                        clonedNum.Add(lo);
                    }
                    if (lo.Element(w + "startOverride") == null)
                    {
                        lo.Add(new XElement(w + "startOverride", new XAttribute(w + "val", 1)));
                    }
                }

                targetNumbering.Root.Add(clonedNum);
            }

            // 5) Update paragraphs
            var updatedParagraphs = new List<XElement>();
            foreach (var para in sourceDoc.MainDocumentPart.Document.Body.Elements<Paragraph>())
            {
                var paraClone = XElement.Parse(para.OuterXml);

                var pPr = paraClone.Element(w + "pPr");
                if (pPr == null)
                {
                    pPr = new XElement(w + "pPr");
                    paraClone.AddFirst(pPr);
                }

                var numPr = pPr.Element(w + "numPr");
                if (numPr == null)
                {
                    numPr = new XElement(w + "numPr");
                    pPr.Add(numPr);
                }

                var numIdElem = numPr.Element(w + "numId");
                if (numIdElem != null)
                {
                    var valAttr = numIdElem.Attribute(w + "val");
                    if (valAttr != null && int.TryParse(valAttr.Value, out int originalNumId))
                    {
                        if (srcNumToAbsSignature.TryGetValue(originalNumId, out string absSignature))
                        {
                            if (GlobalNumIdMap.TryGetValue((docGuid, originalNumId, absSignature), out int mappedNumId))
                            {
                                // copy ilvl from source paragraph
                                var srcIlvlElem = paraClone.Descendants(w + "ilvl").FirstOrDefault();
                                if (srcIlvlElem != null)
                                {
                                    var ilvlVal = srcIlvlElem.Attribute(w + "val")?.Value ?? "0";
                                    var numPrIlvl = numPr.Element(w + "ilvl");
                                    if (numPrIlvl != null)
                                        numPrIlvl.SetAttributeValue(w + "val", ilvlVal);
                                    else
                                        numPr.Add(new XElement(w + "ilvl", new XAttribute(w + "val", ilvlVal)));
                                }

                                // set mapped numId
                                numIdElem.SetAttributeValue(w + "val", mappedNumId);
                            }
                        }
                    }
                }

                updatedParagraphs.Add(paraClone);
            }

            // 6) Save updated numbering.xml
            using (var ms = new MemoryStream())
            {
                ms.Write(targetBytes, 0, targetBytes.Length);
                ms.Position = 0;
                using (var wDoc = WordprocessingDocument.Open(ms, true))
                {
                    var mainPart = wDoc.MainDocumentPart;
                    var numberingPart = mainPart.NumberingDefinitionsPart ??
                                        mainPart.AddNewPart<NumberingDefinitionsPart>();

                    using (var partStream = numberingPart.GetStream(FileMode.Create, FileAccess.Write))
                    {
                        targetNumbering.Save(partStream);
                    }

                    mainPart.Document.Save();
                }

                ms.Position = 0;
                targetWml = new WmlDocument(targetWml.FileName, ms.ToArray());
            }

            return new NumberingResult
            {
                UpdatedDoc = targetWml,
                UpdatedParagraphs = updatedParagraphs
            };
        }
    }
3
  • 3
    Please provide a minimal reproducible example. Male tje XMLs as small ad possible. To me it looks like this can be reproduced with less elements. Also, provide code that can actually be run Commented Sep 5 at 17:16
  • I am trying to get a chunk of minimal reproducible code to show you. I have not been able to get something that is sizable to give you. All the methods and code required to produce the results are large. I will keep working at it and post when I am able. Commented Sep 9 at 18:00
  • numId.val is an index into the numbering part. You would have to merge the numbering parts of both documents and renumber each use. Perhaps in paragraph properties, perhaps in document styles. Commented Sep 11 at 7:10

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.