Bien, pues después de investigar he conseguido descubrir varias cosas. La primera es que los .docx son en realidad una especie de "zips" con varias carpetas donde hay archivos XML. Los archivos principales son dos:
1.- "word/document.xml": Estructura del .docx
2.- "word/_rels/document.rels.xml": Guarda las relationships del documento
Entonces los enlaces se ponen en el archivo 1 así:
Código XML:
Ver original<w:hyperlink r:id="rIdX">
<w:r w:rsidRPr="008D7595">
<w:rPr>
<w:rStyle w:val="Hipervnculo"/>
</w:rPr>
<w:t>Texto</w:t>
</w:r>
</w:hyperlink>
Excepto el <w:t>, el resto de hijos del hyperlink no sé para qué sirven aunque se puede intuir, y en principio no las voy a usar, con poner el texto me sirve.
Después, en el archivo 2, se ponen los Relationships:
Código XML:
Ver original<Relationship Target="http://www.google.es" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink" Id="rIdX" TargetMode="External"/>
X es el número del id.
Entonces edité el módulo docx y en la función wordrelationships, que es la que añade todos los Relationships antes de guardar el documento, añadí un parámetro para poder pasarle un array de links y que los añadiera también al archivo 2. Lo puse así:
Código Python:
Ver originaldef wordrelationships(relationshiplist, links = []):
relationships = etree.fromstring(
'''<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
</Relationships>'''
)
count = 1
for relationship in relationshiplist:
# Relationship IDs (rId) start at 1.
relationships.append(
makeelement('Relationship', attributes = {
'Id' : 'rId' + str(count),
'Type' : relationship[0],
'Target' : relationship[1]
}, nsprefix = None)
)
count += 1
# A partir de aquí el código es mío
namespace = '{http://schemas.openxmlformats.org/officeDocument/2006/relationships}' # nsprefix = 'r'
if links: # links != []
for obj in links:
relationships.append(
makeelement('Relationship', attributes = {
'Id' : 'rId' + str(count),
'Type' : 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink',
'Target' : obj['target'],
'TargetMode' : obj['mode']
}, attrnsprefix = 'w', tagtext = obj['text'])
)
obj['hyperlink'].set(namespace + 'id', 'rId' + str(count))
count += 1
return relationships
Y aquí surgen varios problemas, como era de esperar
A) En vez de hacer un bucle para relationshiplist y otro para links, parece ser que el de links se queda dentro del otro, y por cada Relationship "estándar" que añade, me añade otra vez el Relationship de mi link.
B) Al crear los elementos pongo tanto nsprefix como attrnsprefix 'w', puesto que en una prueba que hice a mano, al inspeccionar los archivos, el prefijo de los tags es "w:", sin embargo en el archivo generado sale "ns0:".
C) Se supone que cuando se guarda el archivo todo el árbol XML se convierte a string para después escribirlo en el nuevo documento, y se hace mediante el etree de lxml:
Código Python:
Ver original# Serialize our trees into out zip file
treesandfiles = {document:'word/document.xml',
coreprops:'docProps/core.xml',
appprops:'docProps/app.xml',
contenttypes:'[Content_Types].xml',
websettings:'word/webSettings.xml',
wordrelationships:'word/_rels/document.xml.rels'}
for tree in treesandfiles:
log.info('Saving: '+treesandfiles[tree])
treestring = etree.tostring(tree, pretty_print=True)
docxfile.writestr(treesandfiles[tree], treestring)
Al usar el tostring, el parámetro pretty_true es True, así que debería escribirlo con saltos de línea e indentaciones. Sin embargo, cuando me genera el documento, el archivo 2 (el de Relationships) me sale todo en dos líneas:
Código XML:
Ver original<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
<Relationship Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering" Id="rId1" Target="numbering.xml"/><ns0:Relationship xmlns:ns0="http://schemas.openxmlformats.org/wordprocessingml/2006/main" ns0:TargetMode="External" ns0:Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink" ns0:Id="rId2" ns0:Target="http://www.google.es">http://www.google.es</ns0:Relationship><Relationship Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles" Id="rId3" Target="styles.xml"/><ns0:Relationship xmlns:ns0="http://schemas.openxmlformats.org/wordprocessingml/2006/main" ns0:TargetMode="External" ns0:Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink" ns0:Id="rId4" ns0:Target="http://www.google.es">http://www.google.es</ns0:Relationship><Relationship Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings" Id="rId5" Target="settings.xml"/><ns0:Relationship xmlns:ns0="http://schemas.openxmlformats.org/wordprocessingml/2006/main" ns0:TargetMode="External" ns0:Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink" ns0:Id="rId6" ns0:Target="http://www.google.es">http://www.google.es</ns0:Relationship><Relationship Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/webSettings" Id="rId7" Target="webSettings.xml"/><ns0:Relationship xmlns:ns0="http://schemas.openxmlformats.org/wordprocessingml/2006/main" ns0:TargetMode="External" ns0:Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink" ns0:Id="rId8" ns0:Target="http://www.google.es">http://www.google.es</ns0:Relationship><Relationship Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable" Id="rId9" Target="fontTable.xml"/><ns0:Relationship xmlns:ns0="http://schemas.openxmlformats.org/wordprocessingml/2006/main" ns0:TargetMode="External" ns0:Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink" ns0:Id="rId10" ns0:Target="http://www.google.es">http://www.google.es</ns0:Relationship><Relationship Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme" Id="rId11" Target="theme/theme1.xml"/><ns0:Relationship xmlns:ns0="http://schemas.openxmlformats.org/wordprocessingml/2006/main" ns0:TargetMode="External" ns0:Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink" ns0:Id="rId12" ns0:Target="http://www.google.es">http://www.google.es</ns0:Relationship></Relationships>
Ahí también se puede ver lo de que me repite el link que le paso por cada Relationship que añade.
Espero que me podáis ayudar :D
Saludos (: