1515
1616from docxcompose .image import ImageWrapper
1717from docxcompose .properties import CustomProperties
18+ from docxcompose .utils import increment_name
1819from docxcompose .utils import NS
1920from docxcompose .utils import xpath
2021
3637
3738
3839class Composer (object ):
39- def __init__ (self , doc ):
40+ def __init__ (self , doc , preserve_styles = False ):
4041 self .doc = doc
4142 self .pkg = doc .part .package
4243
4344 self .restart_numbering = True
45+ self .preserve_styles = preserve_styles
4446
4547 self .reset_reference_mapping ()
4648
@@ -59,6 +61,7 @@ def append(self, doc, remove_property_fields=True):
5961 def insert (self , index , doc , remove_property_fields = True ):
6062 """Insert the given document at the given index."""
6163 self .reset_reference_mapping ()
64+ self ._preserved_styles = {}
6265
6366 # Remove custom property fields but keep the values
6467 if remove_property_fields :
@@ -299,24 +302,36 @@ def add_styles(self, doc, element):
299302
300303 for style_id in used_style_ids :
301304 our_style_id = self .mapped_style_id (style_id )
302- if our_style_id not in our_style_ids :
305+ # To preserve styles with the same id from added documents, we
306+ # create a copy and append a suffix to the id and name.
307+ if self .preserve_styles and our_style_id in our_style_ids :
308+ if our_style_id not in self ._preserved_styles :
309+ style_element = deepcopy (doc .styles .element .get_by_id (style_id ))
310+ our_style_element = self .doc .styles .element .get_by_id (our_style_id )
311+ if style_element .xml != our_style_element .xml :
312+ new_id = increment_name (our_style_id )
313+ new_name = None
314+ if style_element .name is not None :
315+ new_name = increment_name (style_element .name .val )
316+ while new_id in our_style_ids :
317+ new_id = increment_name (new_id )
318+ if new_name is not None :
319+ new_name = increment_name (new_name )
320+ style_element .styleId = new_id
321+ if new_name is not None :
322+ style_element .name .val = new_name
323+ self .doc .styles .element .append (style_element )
324+ self .add_numberings (doc , style_element )
325+ self .add_linked_styles (doc , style_element )
326+ self ._preserved_styles [our_style_id ] = style_element .styleId
327+ for el in xpath (element , ".//w:tblStyle|.//w:pStyle|.//w:rStyle" ):
328+ el .val = self ._preserved_styles [our_style_id ]
329+ elif our_style_id not in our_style_ids :
303330 style_element = deepcopy (doc .styles .element .get_by_id (style_id ))
304331 if style_element is not None :
305332 self .doc .styles .element .append (style_element )
306333 self .add_numberings (doc , style_element )
307- # Also add linked styles
308- linked_style_ids = xpath (style_element , ".//w:link/@w:val" )
309- if linked_style_ids :
310- linked_style_id = linked_style_ids [0 ]
311- our_linked_style_id = self .mapped_style_id (linked_style_id )
312- if our_linked_style_id not in our_style_ids :
313- our_linked_style = doc .styles .element .get_by_id (
314- linked_style_id
315- )
316- if our_linked_style is not None :
317- self .doc .styles .element .append (
318- deepcopy (our_linked_style )
319- )
334+ self .add_linked_styles (doc , style_element )
320335 else :
321336 # Create a mapping for abstractNumIds used in existing styles
322337 # This is used when adding numberings to avoid having multiple
@@ -360,6 +375,17 @@ def add_styles(self, doc, element):
360375 # Update our style ids
361376 our_style_ids = [s .style_id for s in self .doc .styles ]
362377
378+ def add_linked_styles (self , doc , element ):
379+ linked_style_ids = xpath (element , ".//w:link/@w:val" )
380+ if linked_style_ids :
381+ linked_style_id = linked_style_ids [0 ]
382+ our_linked_style_id = self .mapped_style_id (linked_style_id )
383+ our_style_ids = [s .style_id for s in self .doc .styles ]
384+ if our_linked_style_id not in our_style_ids :
385+ our_linked_style = doc .styles .element .get_by_id (linked_style_id )
386+ if our_linked_style is not None :
387+ self .doc .styles .element .append (deepcopy (our_linked_style ))
388+
363389 def add_numberings (self , doc , element ):
364390 """Add numberings from the given document used in the given element."""
365391 # Search for numbering references
0 commit comments