Уведомления

Группа в Telegram: @pythonsu

#1 Сен. 10, 2015 11:10:26

Olleggerr
Зарегистрирован: 2015-09-10
Сообщения: 4
Репутация: +  0  -
Профиль   Отправить e-mail  

Работа с xml файлом.

Здравствуйте, я чайник, но решил соорудить какую нибудь полезную прогу. Суть в том что из zip контейнера .docx файла берется document.xml, потом к примеру с ним выполняются некоторые операции(вроде замены слов и т.д.), но я столкнулся с проблемой. При использовании функции str() от прочтенных строк все русские слова превращаются в подобное.
\xd0\x9d\xd0\xb5\xd0\xba\xd0\xbe\xd1\x82\xd0\xbe\xd1\x80\xd1\x8b\xd0\xb9
А при использование метода .decode() все слова в порядке, но после записи xml файла, он не читается.

z = ZipFile("Some text.docx", "r")
file = z.open("word/document.xml").read().decode()
f = open('temp/document.xml', 'w')
f.write(file)

Знающие xml подскажите!

Заранее спасибо!

Прикреплённый файлы:
attachment document.xml (1,8 KБ)

Офлайн

#2 Сен. 10, 2015 13:02:10

J.R.
Зарегистрирован: 2015-07-18
Сообщения: 147
Репутация: +  16  -
Профиль  

Работа с xml файлом.

.

Отредактировано J.R. (Фев. 28, 2016 12:45:43)

Офлайн

#3 Сен. 10, 2015 13:19:37

Olleggerr
Зарегистрирован: 2015-09-10
Сообщения: 4
Репутация: +  0  -
Профиль   Отправить e-mail  

Работа с xml файлом.

J.R.
Можете тогда подсказать как изменить то, в какой кодировке будет записываться файл, ибо я уже совершенно потерян.

Офлайн

#4 Сен. 10, 2015 13:39:13

Olleggerr
Зарегистрирован: 2015-09-10
Сообщения: 4
Репутация: +  0  -
Профиль   Отправить e-mail  

Работа с xml файлом.

Все решено, спасибо мануалам питона и J.R., нужно было всего лишь открыть файл для записи в определенной кодировке.

z = ZipFile("Some text.docx", "r")
file = z.open("word/document.xml").read().decode("utf-8")
f = open('temp/document.xml', 'w', encoding="utf-8")
f.write(file)

Офлайн

#5 Сен. 10, 2015 21:04:09

doza_and
От:
Зарегистрирован: 2010-08-15
Сообщения: 4138
Репутация: +  253  -
Профиль   Отправить e-mail  

Работа с xml файлом.

1. open тоже допускает указание кодировки.
2. чтобы получилось что-то полезное надо xml назад запихать.
3. есть https://python-docx.readthedocs.org/en/latest/
4. заменить слово будет сложно. MS Word произвольно режет текст на так называемые раны. Легко может оказаться что ваше слово разорвано и в его середину напихано 10 к служебной информации.



Офлайн

#6 Сен. 10, 2015 21:38:31

Olleggerr
Зарегистрирован: 2015-09-10
Сообщения: 4
Репутация: +  0  -
Профиль   Отправить e-mail  

Работа с xml файлом.

doza_and
Благодарю, но у меня немного другая цель(заменить кодовые слова тем, что приходит из интерфейса) вроде, пока тестил всё получалось, как в полной программе работать будет не знаю, но за библиотеку все равно спасибо.

Офлайн

#7 Сен. 10, 2015 22:51:14

doza_and
От:
Зарегистрирован: 2010-08-15
Сообщения: 4138
Репутация: +  253  -
Профиль   Отправить e-mail  

Работа с xml файлом.

Чем раньше вы выкинете форд из своего инструментария тем вам будет легче!!!
Эта фиговина заменяет ключевые слова в виде ${name} которые находятся в вордовом документе на значения из словаря в файле данных. (точнее это ограниченая версия mako templates).
Такой ход был выбран поскольку надо было работать и с doc и с docx. И собирать ошметки слов очень накладно.
Предупреждаю - эта штука медленная.
Посмотрите внимательно - не код а море заплаток. см. первое предложение поста.
По идее не хватает предопределенных функций для вставки табличных данных.

#!/usr/bin/env python
# -*- coding: utf-8 -*-
u"""
mako templates by win32com in winword
"""
import mako
from mako.lookup import TemplateLookup
from mako.template import Template
from mako.lexer import Lexer
import argparse
import codecs
import os
import re
import win32com.client
from win32com.client import constants as c
import time
import shutil
import yaml
def subst_doc(word,doc,reprule):
    word.Selection.HomeKey(c.wdStory)
    fnd= word.Selection.Find
    fnd.ClearFormatting()
    fnd.Forward = True
    fnd.Format = False
    fnd.MatchCase = False
    fnd.MatchWholeWord = False
    fnd.MatchWildcards = False
    fnd.MatchSoundsLike = False
    fnd.MatchAllWordForms = False
    for a,b in reprule:
        fnd.Text = a.replace(u"\n",u"\r")
        fnd.Execute()
        e=word.Selection.End
        word.Selection.InsertAfter(b.replace(u"\n",u"\r"))
        e1=word.Selection.End
        word.Selection.End=e
        word.Selection.Cut()
#        word.Selection.Collapse(c.wdCollapseEnd)
#in_file = u"ref.docx"
#out_file = u"ref1.docx"
#data_file = u"data.yaml"
def convert(in_file, out_file, data_file,show_word=0):
    if data_file:
        with codecs.open(data_file,"r",encoding='utf-8') as f:
            data =yaml.load(f)
    else:
        data={}
    if in_file!=out_file:
        if os.path.exists(out_file):
            os.remove(out_file)
        shutil.copy(in_file,out_file)
    word = win32com.client.gencache.EnsureDispatch("Word.Application")
    word.Visible = show_word
    time.sleep(1)
    word.Documents.Open(os.path.abspath(out_file))
    doc = word.Documents(word.ActiveDocument())
    from win32com.client import constants as c
    try:
        text_b = doc.Content.Text.replace(u"\r",u"\n")
        lk= Lexer(text_b)
        text_a = Template(text_b).render(**data)
        res=lk.parse()
        reprule=[]# что ищем и на что заменяем
        i0_b=0
        i0_a=0
        expr_beg_b=0
        expr_beg_a=0
        expr_end_b=0
        expr_end_a=0
        control_count=0
        for i in res.nodes:
            if type(i) is mako.parsetree.Text:
                ct=i.content
                # нашли блок текста
                pos_b=text_b[i0_b:].find(ct)
                pos_a=text_a[i0_a:].find(ct)
                pos_b+=i0_b
                pos_a+=i0_a
                # если мы не внутри циклов то это конец предыдущего выражения
                if control_count==0:
                    expr_end_b=pos_b
                    expr_end_a=pos_a
                    # если есть конец то сбрасываем выражения в список
                    if expr_end_b>expr_beg_b:
                        reprule.append([text_b[expr_beg_b:expr_end_b],text_a[expr_beg_a:expr_end_a]])
                # передвинули стартовую позицию на конец текста
                i0_b=pos_b+len(ct)
                i0_a=pos_a+len(ct)
                if control_count==0:
                    # ставим начало на конец найденного текста
                    expr_beg_b=i0_b
                    expr_beg_a=i0_a
            else:
                # тут контролирем только вложенность for и if
                if type(i) is mako.parsetree.ControlLine:
                    if i.isend:
                        control_count-=1
                    else:
                        control_count+=1
            # если последним был шаблон то добразываем и его
            if not type(res.nodes[-1]) is mako.parsetree.Text:
                reprule.append([text_b[expr_beg_b:],text_a[expr_beg_a:]])
        subst_doc(word,doc,reprule)
        doc.Save()
    finally:
        word.Quit()
if __name__ == '__main__':
    parser = argparse.ArgumentParser(prog="word_mako",description="substitute data to word_mako infile outfile")
    parser.add_argument("-d","--data",default="",help=u"dile with data")
    parser.add_argument("-o","--output", help=u"output file")
    parser.add_argument("-w","--word", action='store_true', help=u"output file")
    parser.add_argument("file",help=u"input file")
    args = parser.parse_args()
    convert(args.file, args.output, args.data, show_word=args.word)



Отредактировано doza_and (Сен. 10, 2015 22:56:29)

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version