ReferenceAdder.cs 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639
  1. // Copyright (c) Microsoft. All rights reserved.
  2. // Licensed under the MIT license. See LICENSE file in the project root for full license information.
  3. using System;
  4. using System.IO;
  5. using System.Linq;
  6. using System.Xml;
  7. using System.Xml.Linq;
  8. using System.Xml.XPath;
  9. using DocumentFormat.OpenXml.Packaging;
  10. namespace OpenXmlPowerTools
  11. {
  12. public partial class WmlDocument : OpenXmlPowerToolsDocument
  13. {
  14. public WmlDocument AddToc(string xPath, string switches, string title, int? rightTabPos)
  15. {
  16. return (WmlDocument)ReferenceAdder.AddToc(this, xPath, switches, title, rightTabPos);
  17. }
  18. public WmlDocument AddTof(string xPath, string switches, int? rightTabPos)
  19. {
  20. return (WmlDocument)ReferenceAdder.AddTof(this, xPath, switches, rightTabPos);
  21. }
  22. public WmlDocument AddToa(string xPath, string switches, int? rightTabPos)
  23. {
  24. return (WmlDocument)ReferenceAdder.AddToa(this, xPath, switches, rightTabPos);
  25. }
  26. }
  27. public class ReferenceAdder
  28. {
  29. public static WmlDocument AddToc(WmlDocument document, string xPath, string switches, string title, int? rightTabPos)
  30. {
  31. using (OpenXmlMemoryStreamDocument streamDoc = new OpenXmlMemoryStreamDocument(document))
  32. {
  33. using (WordprocessingDocument doc = streamDoc.GetWordprocessingDocument())
  34. {
  35. AddToc(doc, xPath, switches, title, rightTabPos);
  36. }
  37. return streamDoc.GetModifiedWmlDocument();
  38. }
  39. }
  40. public static void AddToc(WordprocessingDocument doc, string xPath, string switches, string title, int? rightTabPos)
  41. {
  42. UpdateFontTablePart(doc);
  43. UpdateStylesPartForToc(doc);
  44. UpdateStylesWithEffectsPartForToc(doc);
  45. if (title == null)
  46. title = "Contents";
  47. if (rightTabPos == null)
  48. rightTabPos = 9350;
  49. // {0} tocTitle (default = "Contents")
  50. // {1} rightTabPosition (default = 9350)
  51. // {2} switches
  52. String xmlString =
  53. @"<w:sdt xmlns:w='http://schemas.openxmlformats.org/wordprocessingml/2006/main'>
  54. <w:sdtPr>
  55. <w:docPartObj>
  56. <w:docPartGallery w:val='Table of Contents'/>
  57. <w:docPartUnique/>
  58. </w:docPartObj>
  59. </w:sdtPr>
  60. <w:sdtEndPr>
  61. <w:rPr>
  62. <w:rFonts w:asciiTheme='minorHAnsi' w:cstheme='minorBidi' w:eastAsiaTheme='minorHAnsi' w:hAnsiTheme='minorHAnsi'/>
  63. <w:color w:val='auto'/>
  64. <w:sz w:val='22'/>
  65. <w:szCs w:val='22'/>
  66. <w:lang w:eastAsia='en-US'/>
  67. </w:rPr>
  68. </w:sdtEndPr>
  69. <w:sdtContent>
  70. <w:p>
  71. <w:pPr>
  72. <w:pStyle w:val='TOCHeading'/>
  73. </w:pPr>
  74. <w:r>
  75. <w:t>{0}</w:t>
  76. </w:r>
  77. </w:p>
  78. <w:p>
  79. <w:pPr>
  80. <w:pStyle w:val='TOC1'/>
  81. <w:tabs>
  82. <w:tab w:val='right' w:leader='dot' w:pos='{1}'/>
  83. </w:tabs>
  84. <w:rPr>
  85. <w:noProof/>
  86. </w:rPr>
  87. </w:pPr>
  88. <w:r>
  89. <w:fldChar w:fldCharType='begin' w:dirty='true'/>
  90. </w:r>
  91. <w:r>
  92. <w:instrText xml:space='preserve'> {2} </w:instrText>
  93. </w:r>
  94. <w:r>
  95. <w:fldChar w:fldCharType='separate'/>
  96. </w:r>
  97. </w:p>
  98. <w:p>
  99. <w:r>
  100. <w:rPr>
  101. <w:b/>
  102. <w:bCs/>
  103. <w:noProof/>
  104. </w:rPr>
  105. <w:fldChar w:fldCharType='end'/>
  106. </w:r>
  107. </w:p>
  108. </w:sdtContent>
  109. </w:sdt>";
  110. XmlReader sdtReader = XmlReader.Create(new StringReader(String.Format(xmlString, title, rightTabPos, switches)));
  111. XElement sdt = XElement.Load(sdtReader);
  112. XmlNamespaceManager namespaceManager;
  113. XDocument mainXDoc = doc.MainDocumentPart.GetXDocument(out namespaceManager);
  114. namespaceManager.AddNamespace("w", "http://schemas.openxmlformats.org/wordprocessingml/2006/main");
  115. XElement addBefore = mainXDoc.XPathSelectElement(xPath, namespaceManager);
  116. if (addBefore == null)
  117. throw new OpenXmlPowerToolsException("XPath expression did not select an element");
  118. addBefore.AddBeforeSelf(sdt);
  119. doc.MainDocumentPart.PutXDocument();
  120. XDocument settingsXDoc = doc.MainDocumentPart.DocumentSettingsPart.GetXDocument();
  121. XElement updateFields = settingsXDoc.Descendants(W.updateFields).FirstOrDefault();
  122. if (updateFields != null)
  123. updateFields.Attribute(W.val).Value = "true";
  124. else
  125. {
  126. updateFields = new XElement(W.updateFields,
  127. new XAttribute(W.val, "true"));
  128. settingsXDoc.Root.Add(updateFields);
  129. }
  130. doc.MainDocumentPart.DocumentSettingsPart.PutXDocument();
  131. }
  132. public static WmlDocument AddTof(WmlDocument document, string xPath, string switches, int? rightTabPos)
  133. {
  134. using (OpenXmlMemoryStreamDocument streamDoc = new OpenXmlMemoryStreamDocument(document))
  135. {
  136. using (WordprocessingDocument doc = streamDoc.GetWordprocessingDocument())
  137. {
  138. AddTof(doc, xPath, switches, rightTabPos);
  139. }
  140. return streamDoc.GetModifiedWmlDocument();
  141. }
  142. }
  143. public static void AddTof(WordprocessingDocument doc, string xPath, string switches, int? rightTabPos)
  144. {
  145. UpdateFontTablePart(doc);
  146. UpdateStylesPartForTof(doc);
  147. UpdateStylesWithEffectsPartForTof(doc);
  148. if (rightTabPos == null)
  149. rightTabPos = 9350;
  150. // {0} rightTabPosition (default = 9350)
  151. // {1} switches
  152. string xmlString =
  153. @"<w:p xmlns:w='http://schemas.openxmlformats.org/wordprocessingml/2006/main'>
  154. <w:pPr>
  155. <w:pStyle w:val='TableofFigures'/>
  156. <w:tabs>
  157. <w:tab w:val='right' w:leader='dot' w:pos='{0}'/>
  158. </w:tabs>
  159. <w:rPr>
  160. <w:noProof/>
  161. </w:rPr>
  162. </w:pPr>
  163. <w:r>
  164. <w:fldChar w:fldCharType='begin' dirty='true'/>
  165. </w:r>
  166. <w:r>
  167. <w:instrText xml:space='preserve'> {1} </w:instrText>
  168. </w:r>
  169. <w:r>
  170. <w:fldChar w:fldCharType='separate'/>
  171. </w:r>
  172. <w:r>
  173. <w:fldChar w:fldCharType='end'/>
  174. </w:r>
  175. </w:p>";
  176. XDocument mainXDoc = doc.MainDocumentPart.GetXDocument();
  177. XmlReader paragraphReader = XmlReader.Create(new StringReader(String.Format(xmlString, rightTabPos, switches)));
  178. XElement paragraph = XElement.Load(paragraphReader);
  179. XmlNameTable nameTable = paragraphReader.NameTable;
  180. XmlNamespaceManager namespaceManager = new XmlNamespaceManager(nameTable);
  181. namespaceManager.AddNamespace("w", "http://schemas.openxmlformats.org/wordprocessingml/2006/main");
  182. XElement addBefore = mainXDoc.XPathSelectElement(xPath, namespaceManager);
  183. if (addBefore == null)
  184. throw new OpenXmlPowerToolsException("XPath expression did not select an element");
  185. addBefore.AddBeforeSelf(paragraph);
  186. doc.MainDocumentPart.PutXDocument();
  187. XDocument settingsXDoc = doc.MainDocumentPart.DocumentSettingsPart.GetXDocument();
  188. XElement updateFields = settingsXDoc.Descendants(W.updateFields).FirstOrDefault();
  189. if (updateFields != null)
  190. updateFields.Attribute(W.val).Value = "true";
  191. else
  192. {
  193. updateFields = new XElement(W.updateFields,
  194. new XAttribute(W.val, "true"));
  195. settingsXDoc.Root.Add(updateFields);
  196. }
  197. doc.MainDocumentPart.DocumentSettingsPart.PutXDocument();
  198. }
  199. public static WmlDocument AddToa(WmlDocument document, string xPath, string switches, int? rightTabPos)
  200. {
  201. using (OpenXmlMemoryStreamDocument streamDoc = new OpenXmlMemoryStreamDocument(document))
  202. {
  203. using (WordprocessingDocument doc = streamDoc.GetWordprocessingDocument())
  204. {
  205. AddToa(doc, xPath, switches, rightTabPos);
  206. }
  207. return streamDoc.GetModifiedWmlDocument();
  208. }
  209. }
  210. public static void AddToa(WordprocessingDocument doc, string xPath, string switches, int? rightTabPos)
  211. {
  212. UpdateFontTablePart(doc);
  213. UpdateStylesPartForToa(doc);
  214. UpdateStylesWithEffectsPartForToa(doc);
  215. if (rightTabPos == null)
  216. rightTabPos = 9350;
  217. // {0} rightTabPosition (default = 9350)
  218. // {1} switches
  219. string xmlString =
  220. @"<w:p xmlns:w='http://schemas.openxmlformats.org/wordprocessingml/2006/main'>
  221. <w:pPr>
  222. <w:pStyle w:val='TOAHeading'/>
  223. <w:tabs>
  224. <w:tab w:val='right'
  225. w:leader='dot'
  226. w:pos='{0}'/>
  227. </w:tabs>
  228. <w:rPr>
  229. <w:rFonts w:asciiTheme='minorHAnsi'
  230. w:eastAsiaTheme='minorEastAsia'
  231. w:hAnsiTheme='minorHAnsi'
  232. w:cstheme='minorBidi'/>
  233. <w:b w:val='0'/>
  234. <w:bCs w:val='0'/>
  235. <w:noProof/>
  236. <w:sz w:val='22'/>
  237. <w:szCs w:val='22'/>
  238. </w:rPr>
  239. </w:pPr>
  240. <w:r>
  241. <w:fldChar w:fldCharType='begin'/>
  242. </w:r>
  243. <w:r>
  244. <w:instrText xml:space='preserve'> {1} </w:instrText>
  245. </w:r>
  246. <w:r>
  247. <w:fldChar w:fldCharType='separate'/>
  248. </w:r>
  249. <w:r>
  250. <w:fldChar w:fldCharType='end'/>
  251. </w:r>
  252. </w:p>";
  253. XDocument mainXDoc = doc.MainDocumentPart.GetXDocument();
  254. XmlReader paragraphReader = XmlReader.Create(new StringReader(String.Format(xmlString, rightTabPos, switches)));
  255. XElement paragraph = XElement.Load(paragraphReader);
  256. XmlNameTable nameTable = paragraphReader.NameTable;
  257. XmlNamespaceManager namespaceManager = new XmlNamespaceManager(nameTable);
  258. namespaceManager.AddNamespace("w", "http://schemas.openxmlformats.org/wordprocessingml/2006/main");
  259. XElement addBefore = mainXDoc.XPathSelectElement(xPath, namespaceManager);
  260. if (addBefore == null)
  261. throw new OpenXmlPowerToolsException("XPath expression did not select an element");
  262. addBefore.AddBeforeSelf(paragraph);
  263. doc.MainDocumentPart.PutXDocument();
  264. XDocument settingsXDoc = doc.MainDocumentPart.DocumentSettingsPart.GetXDocument();
  265. XElement updateFields = settingsXDoc.Descendants(W.updateFields).FirstOrDefault();
  266. if (updateFields != null)
  267. updateFields.Attribute(W.val).Value = "true";
  268. else
  269. {
  270. updateFields = new XElement(W.updateFields,
  271. new XAttribute(W.val, "true"));
  272. settingsXDoc.Root.Add(updateFields);
  273. }
  274. doc.MainDocumentPart.DocumentSettingsPart.PutXDocument();
  275. }
  276. private static void AddElementIfMissing(XDocument partXDoc, XElement existing, string newElement)
  277. {
  278. if (existing != null)
  279. return;
  280. XElement newXElement = XElement.Parse(newElement);
  281. newXElement.Attributes().Where(a => a.IsNamespaceDeclaration).Remove();
  282. partXDoc.Root.Add(newXElement);
  283. }
  284. private static void UpdateFontTablePart(WordprocessingDocument doc)
  285. {
  286. FontTablePart fontTablePart = doc.MainDocumentPart.FontTablePart;
  287. if (fontTablePart == null)
  288. throw new Exception("Todo need to insert font table part");
  289. XDocument fontTableXDoc = fontTablePart.GetXDocument();
  290. AddElementIfMissing(fontTableXDoc,
  291. fontTableXDoc
  292. .Root
  293. .Elements(W.font)
  294. .Where(e => (string)e.Attribute(W.name) == "Tahoma")
  295. .FirstOrDefault(),
  296. @"<w:font w:name='Tahoma' xmlns:w='http://schemas.openxmlformats.org/wordprocessingml/2006/main'>
  297. <w:panose1 w:val='020B0604030504040204'/>
  298. <w:charset w:val='00'/>
  299. <w:family w:val='swiss'/>
  300. <w:pitch w:val='variable'/>
  301. <w:sig w:usb0='E1002EFF' w:usb1='C000605B' w:usb2='00000029' w:usb3='00000000' w:csb0='000101FF' w:csb1='00000000'/>
  302. </w:font>");
  303. fontTablePart.PutXDocument();
  304. }
  305. private static void UpdatePartForToc(OpenXmlPart part)
  306. {
  307. XDocument xDoc = part.GetXDocument();
  308. AddElementIfMissing(
  309. xDoc,
  310. xDoc.Root.Elements(W.style)
  311. .Where(e => (string)e.Attribute(W.type) == "paragraph" && (string)e.Attribute(W.styleId) == "TOCHeading")
  312. .FirstOrDefault(),
  313. @"<w:style w:type='paragraph' w:styleId='TOCHeading' xmlns:w='http://schemas.openxmlformats.org/wordprocessingml/2006/main'>
  314. <w:name w:val='TOC Heading'/>
  315. <w:basedOn w:val='Heading1'/>
  316. <w:next w:val='Normal'/>
  317. <w:uiPriority w:val='39'/>
  318. <w:semiHidden/>
  319. <w:unhideWhenUsed/>
  320. <w:qFormat/>
  321. <w:pPr>
  322. <w:outlineLvl w:val='9'/>
  323. </w:pPr>
  324. <w:rPr>
  325. <w:lang w:eastAsia='ja-JP'/>
  326. </w:rPr>
  327. </w:style>");
  328. AddElementIfMissing(
  329. xDoc,
  330. xDoc.Root.Elements(W.style)
  331. .Where(e => (string)e.Attribute(W.type) == "paragraph" && (string)e.Attribute(W.styleId) == "TOC1")
  332. .FirstOrDefault(),
  333. @"<w:style w:type='paragraph' w:styleId='TOC1' xmlns:w='http://schemas.openxmlformats.org/wordprocessingml/2006/main'>
  334. <w:name w:val='toc 1'/>
  335. <w:basedOn w:val='Normal'/>
  336. <w:next w:val='Normal'/>
  337. <w:autoRedefine/>
  338. <w:uiPriority w:val='39'/>
  339. <w:unhideWhenUsed/>
  340. <w:pPr>
  341. <w:spacing w:after='100'/>
  342. </w:pPr>
  343. </w:style>");
  344. AddElementIfMissing(
  345. xDoc,
  346. xDoc.Root.Elements(W.style)
  347. .Where(e => (string)e.Attribute(W.type) == "paragraph" && (string)e.Attribute(W.styleId) == "TOC2")
  348. .FirstOrDefault(),
  349. @"<w:style w:type='paragraph' w:styleId='TOC2' xmlns:w='http://schemas.openxmlformats.org/wordprocessingml/2006/main'>
  350. <w:name w:val='toc 2'/>
  351. <w:basedOn w:val='Normal'/>
  352. <w:next w:val='Normal'/>
  353. <w:autoRedefine/>
  354. <w:uiPriority w:val='39'/>
  355. <w:unhideWhenUsed/>
  356. <w:pPr>
  357. <w:spacing w:after='100'/>
  358. <w:ind w:left='220'/>
  359. </w:pPr>
  360. </w:style>");
  361. AddElementIfMissing(
  362. xDoc,
  363. xDoc.Root.Elements(W.style)
  364. .Where(e => (string)e.Attribute(W.type) == "paragraph" && (string)e.Attribute(W.styleId) == "TOC3")
  365. .FirstOrDefault(),
  366. @"<w:style w:type='paragraph' w:styleId='TOC3' xmlns:w='http://schemas.openxmlformats.org/wordprocessingml/2006/main'>
  367. <w:name w:val='toc 3'/>
  368. <w:basedOn w:val='Normal'/>
  369. <w:next w:val='Normal'/>
  370. <w:autoRedefine/>
  371. <w:uiPriority w:val='39'/>
  372. <w:unhideWhenUsed/>
  373. <w:pPr>
  374. <w:spacing w:after='100'/>
  375. <w:ind w:left='440'/>
  376. </w:pPr>
  377. </w:style>");
  378. AddElementIfMissing(
  379. xDoc,
  380. xDoc.Root.Elements(W.style)
  381. .Where(e => (string)e.Attribute(W.type) == "paragraph" && (string)e.Attribute(W.styleId) == "TOC4")
  382. .FirstOrDefault(),
  383. @"<w:style w:type='paragraph' w:styleId='TOC4' xmlns:w='http://schemas.openxmlformats.org/wordprocessingml/2006/main'>
  384. <w:name w:val='toc 4'/>
  385. <w:basedOn w:val='Normal'/>
  386. <w:next w:val='Normal'/>
  387. <w:autoRedefine/>
  388. <w:uiPriority w:val='39'/>
  389. <w:unhideWhenUsed/>
  390. <w:pPr>
  391. <w:spacing w:after='100'/>
  392. <w:ind w:left='660'/>
  393. </w:pPr>
  394. </w:style>");
  395. AddElementIfMissing(
  396. xDoc,
  397. xDoc.Root.Elements(W.style)
  398. .Where(e => (string)e.Attribute(W.type) == "character" && (string)e.Attribute(W.styleId) == "Hyperlink")
  399. .FirstOrDefault(),
  400. @"<w:style w:type='character' w:styleId='Hyperlink' xmlns:w='http://schemas.openxmlformats.org/wordprocessingml/2006/main'>
  401. <w:name w:val='Hyperlink'/>
  402. <w:basedOn w:val='DefaultParagraphFont'/>
  403. <w:uiPriority w:val='99'/>
  404. <w:unhideWhenUsed/>
  405. <w:rPr>
  406. <w:color w:val='0000FF' w:themeColor='hyperlink'/>
  407. <w:u w:val='single'/>
  408. </w:rPr>
  409. </w:style>");
  410. AddElementIfMissing(
  411. xDoc,
  412. xDoc.Root.Elements(W.style)
  413. .Where(e => (string)e.Attribute(W.type) == "paragraph" && (string)e.Attribute(W.styleId) == "BalloonText")
  414. .FirstOrDefault(),
  415. @"<w:style w:type='paragraph' w:styleId='BalloonText' xmlns:w='http://schemas.openxmlformats.org/wordprocessingml/2006/main'>
  416. <w:name w:val='Balloon Text'/>
  417. <w:basedOn w:val='Normal'/>
  418. <w:link w:val='BalloonTextChar'/>
  419. <w:uiPriority w:val='99'/>
  420. <w:semiHidden/>
  421. <w:unhideWhenUsed/>
  422. <w:pPr>
  423. <w:spacing w:after='0' w:line='240' w:lineRule='auto'/>
  424. </w:pPr>
  425. <w:rPr>
  426. <w:rFonts w:ascii='Tahoma' w:hAnsi='Tahoma' w:cs='Tahoma'/>
  427. <w:sz w:val='16'/>
  428. <w:szCs w:val='16'/>
  429. </w:rPr>
  430. </w:style>");
  431. AddElementIfMissing(
  432. xDoc,
  433. xDoc.Root.Elements(W.style)
  434. .Where(e => (string)e.Attribute(W.type) == "character" &&
  435. (bool?)e.Attribute(W.customStyle) == true && (string)e.Attribute(W.styleId) == "BalloonTextChar")
  436. .FirstOrDefault(),
  437. @"<w:style w:type='character' w:customStyle='1' w:styleId='BalloonTextChar' xmlns:w='http://schemas.openxmlformats.org/wordprocessingml/2006/main'>
  438. <w:name w:val='Balloon Text Char'/>
  439. <w:basedOn w:val='DefaultParagraphFont'/>
  440. <w:link w:val='BalloonText'/>
  441. <w:uiPriority w:val='99'/>
  442. <w:semiHidden/>
  443. <w:rPr>
  444. <w:rFonts w:ascii='Tahoma' w:hAnsi='Tahoma' w:cs='Tahoma'/>
  445. <w:sz w:val='16'/>
  446. <w:szCs w:val='16'/>
  447. </w:rPr>
  448. </w:style>");
  449. part.PutXDocument();
  450. }
  451. private static void UpdateStylesPartForToc(WordprocessingDocument doc)
  452. {
  453. StylesPart stylesPart = doc.MainDocumentPart.StyleDefinitionsPart;
  454. if (stylesPart == null)
  455. return;
  456. UpdatePartForToc(stylesPart);
  457. }
  458. private static void UpdateStylesWithEffectsPartForToc(WordprocessingDocument doc)
  459. {
  460. StylesWithEffectsPart stylesWithEffectsPart = doc.MainDocumentPart.StylesWithEffectsPart;
  461. if (stylesWithEffectsPart == null)
  462. return;
  463. UpdatePartForToc(stylesWithEffectsPart);
  464. }
  465. private static void UpdatePartForTof(OpenXmlPart part)
  466. {
  467. XDocument xDoc = part.GetXDocument();
  468. AddElementIfMissing(
  469. xDoc,
  470. xDoc.Root.Elements(W.style)
  471. .Where(e => (string)e.Attribute(W.type) == "paragraph" && (string)e.Attribute(W.styleId) == "TableofFigures")
  472. .FirstOrDefault(),
  473. @"<w:style w:type='paragraph' w:styleId='TableofFigures' xmlns:w='http://schemas.openxmlformats.org/wordprocessingml/2006/main'>
  474. <w:name w:val='table of figures'/>
  475. <w:basedOn w:val='Normal'/>
  476. <w:next w:val='Normal'/>
  477. <w:uiPriority w:val='99'/>
  478. <w:unhideWhenUsed/>
  479. <w:pPr>
  480. <w:spacing w:after='0'/>
  481. </w:pPr>
  482. </w:style>");
  483. AddElementIfMissing(
  484. xDoc,
  485. xDoc.Root.Elements(W.style)
  486. .Where(e => (string)e.Attribute(W.type) == "character" && (string)e.Attribute(W.styleId) == "Hyperlink")
  487. .FirstOrDefault(),
  488. @"<w:style w:type='character' w:styleId='Hyperlink' xmlns:w='http://schemas.openxmlformats.org/wordprocessingml/2006/main'>
  489. <w:name w:val='Hyperlink'/>
  490. <w:basedOn w:val='DefaultParagraphFont'/>
  491. <w:uiPriority w:val='99'/>
  492. <w:unhideWhenUsed/>
  493. <w:rPr>
  494. <w:color w:val='0000FF' w:themeColor='hyperlink'/>
  495. <w:u w:val='single'/>
  496. </w:rPr>
  497. </w:style>");
  498. part.PutXDocument();
  499. }
  500. private static void UpdateStylesPartForTof(WordprocessingDocument doc)
  501. {
  502. StylesPart stylesPart = doc.MainDocumentPart.StyleDefinitionsPart;
  503. if (stylesPart == null)
  504. return;
  505. UpdatePartForTof(stylesPart);
  506. }
  507. private static void UpdateStylesWithEffectsPartForTof(WordprocessingDocument doc)
  508. {
  509. StylesWithEffectsPart stylesWithEffectsPart = doc.MainDocumentPart.StylesWithEffectsPart;
  510. if (stylesWithEffectsPart == null)
  511. return;
  512. UpdatePartForTof(stylesWithEffectsPart);
  513. }
  514. private static void UpdatePartForToa(OpenXmlPart part)
  515. {
  516. XDocument xDoc = part.GetXDocument();
  517. AddElementIfMissing(
  518. xDoc,
  519. xDoc.Root.Elements(W.style)
  520. .Where(e => (string)e.Attribute(W.type) == "paragraph" && (string)e.Attribute(W.styleId) == "TableofAuthorities")
  521. .FirstOrDefault(),
  522. @"<w:style w:type='paragraph'
  523. w:styleId='TableofAuthorities'
  524. xmlns:w='http://schemas.openxmlformats.org/wordprocessingml/2006/main'>
  525. <w:name w:val='table of authorities'/>
  526. <w:basedOn w:val='Normal'/>
  527. <w:next w:val='Normal'/>
  528. <w:uiPriority w:val='99'/>
  529. <w:semiHidden/>
  530. <w:unhideWhenUsed/>
  531. <w:rsid w:val='0090569D'/>
  532. <w:pPr>
  533. <w:spacing w:after='0'/>
  534. <w:ind w:left='220'
  535. w:hanging='220'/>
  536. </w:pPr>
  537. </w:style>");
  538. AddElementIfMissing(
  539. xDoc,
  540. xDoc.Root.Elements(W.style)
  541. .Where(e => (string)e.Attribute(W.type) == "paragraph" && (string)e.Attribute(W.styleId) == "TOAHeading")
  542. .FirstOrDefault(),
  543. @"<w:style w:type='paragraph'
  544. w:styleId='TOAHeading'
  545. xmlns:w='http://schemas.openxmlformats.org/wordprocessingml/2006/main'>
  546. <w:name w:val='toa heading'/>
  547. <w:basedOn w:val='Normal'/>
  548. <w:next w:val='Normal'/>
  549. <w:uiPriority w:val='99'/>
  550. <w:semiHidden/>
  551. <w:unhideWhenUsed/>
  552. <w:rsid w:val='0090569D'/>
  553. <w:pPr>
  554. <w:spacing w:before='120'/>
  555. </w:pPr>
  556. <w:rPr>
  557. <w:rFonts w:asciiTheme='majorHAnsi'
  558. w:eastAsiaTheme='majorEastAsia'
  559. w:hAnsiTheme='majorHAnsi'
  560. w:cstheme='majorBidi'/>
  561. <w:b/>
  562. <w:bCs/>
  563. <w:sz w:val='24'/>
  564. <w:szCs w:val='24'/>
  565. </w:rPr>
  566. </w:style>");
  567. part.PutXDocument();
  568. }
  569. private static void UpdateStylesPartForToa(WordprocessingDocument doc)
  570. {
  571. StylesPart stylesPart = doc.MainDocumentPart.StyleDefinitionsPart;
  572. if (stylesPart == null)
  573. return;
  574. UpdatePartForToa(stylesPart);
  575. }
  576. private static void UpdateStylesWithEffectsPartForToa(WordprocessingDocument doc)
  577. {
  578. StylesWithEffectsPart stylesWithEffectsPart = doc.MainDocumentPart.StylesWithEffectsPart;
  579. if (stylesWithEffectsPart == null)
  580. return;
  581. UpdatePartForToa(stylesWithEffectsPart);
  582. }
  583. }
  584. }