diff --git a/ooxml/XWPF/Usermodel/XWPFAbstractNum.cs b/ooxml/XWPF/Usermodel/XWPFAbstractNum.cs index 1b658ce46..070960429 100644 --- a/ooxml/XWPF/Usermodel/XWPFAbstractNum.cs +++ b/ooxml/XWPF/Usermodel/XWPFAbstractNum.cs @@ -31,7 +31,7 @@ public class XWPFAbstractNum private CT_AbstractNum ctAbstractNum; protected XWPFNumbering numbering; - protected XWPFAbstractNum() + internal XWPFAbstractNum() { this.ctAbstractNum = null; this.numbering = null; @@ -116,6 +116,11 @@ internal void SetLevelTentative(int lvl, bool tentative) else this.ctAbstractNum.lvl[lvl].tentative = ST_OnOff.off; } + + internal void SetCTAbstractNum(CT_AbstractNum ctAbstractNum) + { + this.ctAbstractNum=ctAbstractNum; + } } /// /// Numbering Definition Type diff --git a/ooxml/XWPF/Usermodel/XWPFNumbering.cs b/ooxml/XWPF/Usermodel/XWPFNumbering.cs index 64516f476..5877da2f1 100644 --- a/ooxml/XWPF/Usermodel/XWPFNumbering.cs +++ b/ooxml/XWPF/Usermodel/XWPFNumbering.cs @@ -230,6 +230,14 @@ public XWPFAbstractNum GetAbstractNum(string abstractNumID){ } return null; } + public List GetAbstractNums() + { + return abstractNums; + } + public List GetNums() + { + return nums; + } /** * Compare AbstractNum with abstractNums of this numbering document. * If the content of abstractNum Equals with an abstractNum of the List in numbering @@ -273,13 +281,22 @@ public string AddAbstractNum(XWPFAbstractNum abstractNum) } else { - ctNumbering.AddNewAbstractNum(); - abstractNum.GetAbstractNum().abstractNumId = pos.ToString(); + abstractNum.SetCTAbstractNum(ctNumbering.AddNewAbstractNum()); + abstractNum.GetAbstractNum().abstractNumId = FindNextAbstractNumberingId().ToString(); ctNumbering.SetAbstractNumArray(pos, abstractNum.GetAbstractNum()); } abstractNums.Add(abstractNum); return abstractNum.GetAbstractNum().abstractNumId; } + private long FindNextAbstractNumberingId() + { + long maxId = 0; + foreach(XWPFAbstractNum num in abstractNums) + { + maxId = Math.Max(maxId, long.Parse(num.GetAbstractNum().abstractNumId)); + } + return maxId + 1; + } /// /// Add a new AbstractNum /// diff --git a/testcases/ooxml/XWPF/UserModel/TestXWPFNumbering.cs b/testcases/ooxml/XWPF/UserModel/TestXWPFNumbering.cs index 8498bfc4b..8a8824cdd 100644 --- a/testcases/ooxml/XWPF/UserModel/TestXWPFNumbering.cs +++ b/testcases/ooxml/XWPF/UserModel/TestXWPFNumbering.cs @@ -21,6 +21,8 @@ namespace TestCases.XWPF.UserModel using NPOI.OpenXmlFormats.Wordprocessing; using NPOI.XWPF.UserModel; using NUnit.Framework;using NUnit.Framework.Legacy; + using System; + using System.Linq; [TestFixture] public class TestXWPFNumbering @@ -110,6 +112,56 @@ public void TestOverrideList() CT_NumLvl ctNumLvl = ctNum.GetLvlOverrideArray(0); ClassicAssert.AreEqual("upperLetter", ctNumLvl.lvl.numFmt.val.ToString()); } + [Test] + public void TestAddAbstractNum() + { + using(XWPFDocument doc = XWPFTestDataSamples.OpenSampleDocument("NumberingWithOutOfOrderId.docx")) + { + doc.GetNumbering().AddAbstractNum(new XWPFAbstractNum()); + var count = doc.GetNumbering() + .GetAbstractNums().Select(e=>Int32.Parse(e.GetCTAbstractNum().abstractNumId)).Distinct().Count(); + ClassicAssert.AreEqual(doc.GetNumbering().GetAbstractNums().Count, count); + } + } + [Test] + public void testAddAbstractNumIfAbstractNumNotEqualNull() + { + string abstractNumId = "1"; + XWPFDocument docOut = new XWPFDocument(); + XWPFNumbering numbering = docOut.CreateNumbering(); + + var cTAbstractNum = new CT_AbstractNum(); + // must set the AbstractNumId, Otherwise fail + cTAbstractNum.abstractNumId = abstractNumId; + XWPFAbstractNum abstractNum = new XWPFAbstractNum(cTAbstractNum); + abstractNumId = numbering.AddAbstractNum(abstractNum); + var numId = numbering.AddNum(abstractNumId); + + XWPFDocument docIn = XWPFTestDataSamples.WriteOutAndReadBack(docOut); + numbering = docIn.GetNumbering(); + XWPFNum num = numbering.GetNum(numId); + var compareAbstractNum = num.GetCTNum().abstractNumId.val; + ClassicAssert.AreEqual(abstractNumId, compareAbstractNum); + } + + [Test] + public void testAddAbstractNumIfAbstractNumEqualNull() + { + XWPFDocument docOut = new XWPFDocument(); + XWPFNumbering numbering = docOut.CreateNumbering(); + + XWPFAbstractNum abstractNum = new XWPFAbstractNum(); + var abstractNumId = numbering.AddAbstractNum(abstractNum); + var numId = numbering.AddNum(abstractNumId); + + XWPFDocument docIn = XWPFTestDataSamples.WriteOutAndReadBack(docOut); + + numbering = docIn.GetNumbering(); + XWPFNum num = numbering.GetNum(numId); + + var compareAbstractNum = num.GetCTNum().abstractNumId.val; + ClassicAssert.AreEqual(abstractNumId, compareAbstractNum); + } } } diff --git a/testcases/test-data/document/NumberingWithOutOfOrderId.docx b/testcases/test-data/document/NumberingWithOutOfOrderId.docx new file mode 100644 index 000000000..6c471c43b Binary files /dev/null and b/testcases/test-data/document/NumberingWithOutOfOrderId.docx differ