Tìm hiểu cấu trúc XML của file docx và tùy biến lại gem docxtor

Tìm hiểu cấu trúc XML của file docx

Docx thực chất là một tài liệu Office Open XML được Microsoft phát triển và xuất hiện đầu tiên ở phiên bản Microsoft Office 2007.

Tài liệu này được lưu trữ đóng gói thành file nén ZIP chứa file XML và các file dữ liệu khác. Vì vậy để ví dụ chúng ta có thể tạo một file Docx bằng chương trình Office Word 2010 sau đó giải nén file bằng chương trình nén file thông thường ZIP hoặc Winzar. Sau khi giải nén ta được cấu trúc file như sau:

structure_docx.gif

Cấu trúc cơ bản này gồm:

  • [Content_Types].xml : file này cung cấp thông tin loại MIME được đóng gói trong Docx
  • _rels : thư mục này lưu quan hệ của một relationship part với các thành phần khác
  • file .rel : các file có định dạng .rel này lưu các relationship part. Các ứng dụng sẽ đọc ở file này đầu tiên.
  • docProps/core.xml : file này lưu các thuộc tính chính của một số tài liệu Office Open XML
  • word/_rels : thư mục này chứa các relationsship part của word. Ví dụ, mối quan hệ với file document.xml sẽ được lưu thành file document.xml.rel
  • word/document.xml : đây là file chính chứa các thành phần cho tài liệu Word

Trong bài viết này, chúng ta sẽ chỉ tìm hiểu cấu trúc của 3 file [Content_Types].xml, word/document.xmlword/_rels/document.xml.rel

  1. [Content_Types].xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
   <Default Extension="rels" ContentType=
   "application/vnd.openxmlformats-package.relationships+xml"/>
   <Default Extension="xml" ContentType="application/xml"/>
   <Override PartName="/word/document.xml" ContentType=
   "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml"/>
   <Override PartName="/word/styles.xml" ContentType=
   "application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml"/>
   <Override PartName="/docProps/app.xml" ContentType=
   "application/vnd.openxmlformats-officedocument.extended-properties+xml"/>
   <Override PartName="/word/settings.xml" ContentType=
   "application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml"/>
   <Override PartName="/word/theme/theme1.xml" ContentType=
   "application/vnd.openxmlformats-officedocument.theme+xml"/>
   <Override PartName="/word/fontTable.xml" ContentType=
   "application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml"/>
   <Override PartName="/word/webSettings.xml" ContentType=
   "application/vnd.openxmlformats-officedocument.wordprocessingml.webSettings+xml"/>
   <Override PartName="/docProps/core.xml" ContentType=
   "application/vnd.openxmlformats-package.core-properties+xml"/>
</Types>
  1. word/_rels/document.xml.rels
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<Relationships
 xmlns="http://schemas.microsoft.com/package/2005/06/relationships">
 <Relationship Id="rId1"
 Type="http://schemas.microsoft.com/office/2006/relationships/image"
 Target="http://en.wikipedia.org/images/wiki-en.png"
 TargetMode="External" />
 <Relationship Id="rId2"
 Type="http://schemas.microsoft.com/office/2006/relationships/hyperlink"
 Target="http://www.wikipedia.org"
 TargetMode="External" />
</Relationships>

Xét cấu trúc trên, ta có thể hiểu, những ảnh được tham chiếu trong tài liệu có thể tìm thấy bằng cách tìm các thẻ Relationships có type là http://schemas.microsoft.com/office/2006/relationships/image. Từ file này, ứng dụng chỉ cần đọc ID của các thẻ Relationship để biết được URL. Ví dụ: để nhúng file ảnh vào tài liệu Word, ta chỉ cần sử dụng: <pic:blipFill><a:blip r:embed="rId1"/></pic:blipFill> hoặc <v:imagedata w:rel="rId1" o:title="example" />

  1. word/document.xml

Cấu trúc XML của từng thành phần các bạn có thể tìm hiểu thêm tại đây

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<w:document xmlns:ve="http://schemas.openxmlformats.org/markup-compatibility/2006"
   xmlns:o="urn:schemas-microsoft-com:office:office"
   xmlns:o12="http://schemas.microsoft.com/office/2004/7/core"
   xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
   xmlns:m="http://schemas.microsoft.com/office/omml/2004/12/core"
   xmlns:v="urn:schemas-microsoft-com:vml"
   xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/3/wordprocessingDrawing"
   xmlns:w10="urn:schemas-microsoft-com:office:word"
   xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/3/main">
   <w:body>
    <w:p>
      <w:r w:rsidR="002847EC">
      <w:t>Word 2007 rocks my world!</w:t>
      </w:r>
    </w:p>
   </w:body>
</w:document>

Gem docxtor

Cách sử dụng các bạn có thể tham khảo thêm tại https://github.com/docxtor/docxtor.

Gem này về cơ bản khá dễ sử dụng và được hỗ trợ khá nhiều thành phần hơn so với các Gem Ruby khác. Nhưng nó không hỗ trợ đầy đủ các thành trong một file docx. Các thành phần được hỗ trợ:

  • Header
  • Main body: p, h1, table
  • Style: chỉ hỗ trợ các style cơ bản bold, italic, underline, indent, line_break, font. Tức là các bạn không thể set color cho text được.

Ngoài ra, có một vấn đề khi sử dụng Gem này đó là các file docx được tạo ra khi đọc bở Offcie Word 2007 trở lên sẽ bị báo lỗi: キャプチャ.PNG

Vì vậy nếu bạn muốn sử dụng để tạo 1 file docx với các thuộc tính cơ bản, không quá phức tạp thì có thể lựa chọn sử dụng Gem này.

Nếu dự án của các bạn cần tạo file Docx phức tạp hơn, mình có một gợi ý là các bạn nên sử dụng Apache Poi

Còn nếu dự án của các bạn đã lựa chọn sử dụng Gem này từ đầu nhưng trong quá trình phát triển phát sinh thêm các yêu cầu đòi hỏi các thành phần khác như set color, insert image (giống dự án của mình, hic) thì các bạn có thể tham khảo cách mình tùy biến lại Gem này phía dưới.

Tùy biến Gem docxtor

Để tùy biến, các bạn hãy down code từ Githud về.

Thêm style set color cho text

Set color được set trong thành phần thẻ paragraph vì thế ta sẽ mở file này theo đường dẫn docxtor/lib/docxtor/document/paragraph.rb.

Ta để ý, các thuộc tính PROPERTIES được cài đặt thiếu các thành phần để set color.

Xét cấu trúc XML của phần này:

<w:color w:val="800000"/>
<w:sz w:val="28"/>

Ta có thể sửa lại Gem như sau:

PROPERTIES =
{
  :p => {
    :style => 'pStyle',
    :align => 'jc',
    :font_size_complex => 'szCs',
    :spacing => {
      :name => 'spacing',
      :before => 'before',
      :after => 'after'
    },
    :indent => {
      :name => 'ind',
      :start => 'start',
      :end => 'end',
      :hanging => 'hanging'
    }
  },
  :r => {
    :font_size => 'sz',      #add sz
    :font_color => 'color',  #add color
    :bg_color => 'shd',
    :bold => 'b',
    :italic => 'i',
    :underline => 'u'
  }
}

Thêm thành phần images

Gem docxtor chưa hỗ trợ thành phần image nên để chèn được image vào trong document.xml chúng ta cần tạo thêm file image.rb trong thư mục docxtor/lib/docxtor/document (tham khảo cấu trúc tương tự ở các thành phần khác)

# file lib / docxtor.rb
module Docxtor
  ....

  module Document
    ....
    autoload :Image, 'docxtor/document/image'
  end
module Docxtor
  module Document
    class Image < Element
      def after_initialize(link, *args)
        # Your code goes here...
      end
      def render xml
        # Your code goes here...
      end
    end
  end
end

Trong file docx, một image được chèn vào có cấu trúc xml như sau (bạn có thể google search hoặc tạo 1 file docx và xem nội dung của document.xml):

<w:drawing>
   <wp:inline distT="0" distB="0" distL="0" distR="0">
      <wp:extent cx="1905000" cy="952500" />
      <wp:effectExtent l="0" t="0" r="0" b="0" />
      <wp:docPr id="rId2" name="Picture rId2" />
      <wp:cNvGraphicFramePr>
         <a:graphicFrameLocks xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" noChangeAspect="1" />
      </wp:cNvGraphicFramePr>
      <a:graphic xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main">
         <a:graphicData uri="http://schemas.openxmlformats.org/drawingml/2006/picture">
            <pic:pic xmlns:pic="http://schemas.openxmlformats.org/drawingml/2006/picture">
               <pic:nvPicPr>
                  <pic:cNvPr id="rId2" name="Picture rId2" />
                  <pic:cNvPicPr>
                     <a:picLocks noChangeAspect="1" noChangeArrowheads="1" />
                  </pic:cNvPicPr>
               </pic:nvPicPr>
               <pic:blipFill>
                  <a:blip r:embed="rId2" />
                  <a:srcRect />
                  <a:stretch>
                     <a:fillRect />
                  </a:stretch>
               </pic:blipFill>
               <pic:spPr bwMode="auto">
                  <a:xfrm>
                     <a:off x="0" y="0" />
                     <a:ext cx="1905000" cy="952500" />
                  </a:xfrm>
                  <a:prstGeom prst="rect">
                     <a:avLst />
                  </a:prstGeom>
                  <a:noFill />
                  <a:ln>
                     <a:noFill />
                  </a:ln>
               </pic:spPr>
            </pic:pic>
         </a:graphicData>
      </a:graphic>
   </wp:inline>
</w:drawing>

<wp:extent cx="1905000" cy="952500" /> chính là width và height của imagimage; <a:blip r:embed="rId2" /> chính là đoạn nhúng ảnh từ relationships document.xml.rel thông qua id rId2

Ta có thể đưa viết lại class Image như sau:

module Docxtor
  module Document
    class Image < Element
      AUTO_WIDTH = 5
      AUTO_HEIGHT = 5
      AUTO_INDENT = 0

      def after_initialize(link, *args)
        @rId = 1 # gán tạm thời
        @num = 1 # gán tạm thời
        style = args.shift || {ời
        @width = (style[:width] || AUTO_WIDTH) * 9144000 / 96
        @height = (style[:height] || AUTO_HEIGHT) * 9144000 / 96
        @indent = style[:indent] || AUTO_INDENT
      end

      def render xml
        xml.w :p do
          xml.w :pPr do
            xml.w :ind, "w:left" => @indent
          end
          xml.w :r do
            xml.w :rPr do
              xml.w :noProof
            end
            drawing xml
          end
        end
      end

      def drawing xml
        xml.w :drawing do
          xml.wp :inline, "distT" => "0", "distB" => "0", "distL" => "0", "distR" => "0" do
            xml.wp :extent, "cx" => @width, "cy" => @height
            xml.wp :effectExtent, "l" => "0", "t" => "0", "r" => "0", "b" => "0"
            xml.wp :docPr, "id" => @num, "name" => "Picture #{@num}"
            xml.wp :cNvGraphicFramePr do
              xml.a :graphicFrameLocks, "xmlns:a" => "http://schemas.openxmlformats.org/drawingml/2006/main", "noChangeAspect" => "1"
            end
            xml.a :graphic, "xmlns:a" => "http://schemas.openxmlformats.org/drawingml/2006/main" do
              xml.a :graphicData, "uri" => "http://schemas.openxmlformats.org/drawingml/2006/picture" do
                xml.pic :pic, "xmlns:pic" => "http://schemas.openxmlformats.org/drawingml/2006/picture" do
                  xml.pic :nvPicPr do
                    xml.pic :cNvPr, "id" => "0", "name" => "Picture #{@num}", "descr" => ""
                    xml.pic :cNvPicPr do
                      xml.a :picLocks, "noChangeAspect" => "1", "noChangeArrowheads" => "1"
                    end
                  end
                  xml.pic :blipFill do
                    xml.a :blip, "r:embed" => "#{@rId}" do
                      xml.a :extLst do
                        xml.a :ext, "uri" => "{28A0092B-C50C-407E-A947-70E740481C1C}" do
                          xml.a14 :useLocalDpi, "xmlns:a14" => "http://schemas.microsoft.com/office/drawing/2010/main", "val" => "0"
                        end
                      end
                    end
                    xml.a :srcRect
                    xml.a :stretch do
                      xml.a :fillRect
                    end
                  end
                  xml.pic :spPr, "bwMode" => "auto" do
                    xml.a :xfrm do
                      xml.a :off, "x" => "0", "y" => "0"
                      xml.a :ext, "cx" => @width, "cy" => @height
                    end
                    xml.a :prstGeom, "prst" => "rect" do
                      xml.a :avLst
                    end
                    xml.a :noFill
                    xml.a :ln do
                      xml.a :noFill
                    end
                  end
                end
              end
            end
          end
        end
      end
    end
  end
end

Tuy nhiên làm thế nào lấy được rid, hơn nữa, chúng ta vẫn chưa lưu được file image. Ta hãy quay lại xem cách lưu file của Gem xem sao.

package = Docxtor.generate do
  table_of_contents "Contents"
  h 1, "heading1"
  p "content", :style => 'p2', :i => true, :align => 'center'
end

package.save('test.docx')

Hãy xem class Generator hoạt động thế nào:

module Docxtor
  class Generator
    class << self
      def generate(template, &block)
        template_parser = TemplateParser.new(template)
        parts = template_parser.parts

        # lấy tất cả các thành phần là header và footer lưu vào running_elements và gán vào parts
        running_elements = RunningElementsBuilder.new(&block).elements
        parts += rnning_elements
        # build running_elements thành các relationship part vào file document.xml.rel và gán vào parts
        parts < ReferenceBuilder.new(running_elements)
        # build các thành phần khác vào file document.xml và gán vào parts
        parts << Document::Builder.new(running_elements, &block)
        # đóng gói các parts
        Package::Builder.new(parts)
      enarts
    end
  end
end

Như vậy, các relationship part được lưu ở đây chỉ là header và footer. Ta sẽ tạo thêm relationship part là image khi build Document::Builder.new(running_elements, &block)

Ta sửa như sau:

# file lib/docxtor/document/element.rb
module Docxtor
  module Document
    class Element
      attr_accessor :elements, :xml, :reference

      def self.map(mappings)
        mappings.each do |name, klass|
          define_method(name) do |*args, &block|
            if name == :image
              image_element = RunningElement.new(name, 1, *args)
              @reference.add_element image_element
            end
            elements << klass.new(@reference, *args, &block)
          end
        end
      end
      ......
    end
  end
end

# file lib/docxtor/document/image.rb
module Docxtor
  module Document
    class Image < Element
      ....

      def after_initialize(link, *args)
        @rId = @reference.last_element.reference_id
        @num = @reference.last_element.num
        ....
      end
    end
  end
end

# file lib/docxtor/reference_builder.rb
module Docxtor
  class ReferenceBuilder
    attr_accessor :elements
    ...

    def add_element running_element
      running_element.reference_id = "rId#{elements.length+1}"
      running_element.num = elements.length+1
      @elements << running_element
    end

    def last_element
      @elements.last
    end
    ...
  end
end

# file lib/docxtor/running_element.rb
module Docxtor
  class RunningElement
    attr_accessor :pages, :type, :reference_id, :num

    def initialize type, num, contents, options = {}
      @type = type
      @contents = contents
      @align = options[:align]
      @pages = options[:pages] || :default
      @num = num
    end

    def reference_name
      "#{type}Reference"
    end

    def name
      if @type == :image
        "media/#{@contents.split("/").last}"
      else
        "#{type}#{@num}.xml"
      end
    end
    ....

    def content
      if @type == :image
        return File.read(@contents)
      enend
      ....
    end
  end
end

Cuối cùng, ta sửa lại class Generate như sau:

module Docxtor
  class Generator
    class << self
      def generate(template, &block)
        template_parser = TemplateParser.new(template)
        parts = template_parser.parts

        running_elements = RunningElementsBuilder.new(&block).elements
        reference = ReferenceBuilder.new(running_elements)
        document = Document::Builder.new(reference, &block)

        parts += document.reference.elements
        parts << document.reference
        parts << document
        Package::Builder.new(parts)
      end
    end
  end
end

Sửa lỗi với Office Word 2007

Lỗi này là do cấu trúc của header của các file XML không đúng với định dạng chuẩn của Office Open XML. Ta sẽ sửa lỗi này như sau:

Đầu tiên là sửa cấu trúc file header, file này được generate bởi class running_element, ta sửa như sau:

#file lib/docxtor/running_element.rb
module Docxtor
  class RunningElement
    def content
      if @type == :image
        return File.read(@contents)
      end
      xml = ::Builder::XmlMarkup.new

      if @type == :header
        xml.instruct! :xml, :version => "1.0", :encoding => "UTF-8", :standalone => "yes"
        xml.w :hdr,
          "xmlns:wpc" => "http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas",
          "xmlns:mo" => "http://schemas.microsoft.com/office/mac/office/2008/main",
          "xmlns:mc" => "http://schemas.openxmlformats.org/markup-compatibility/2006",
          "xmlns:mv" => "urn:schemas-microsoft-com:mac:vml",
          "xmlns:o" => "urn:schemas-microsoft-com:office:office",
          "xmlns:r" => "http://schemas.openxmlformats.org/officeDocument/2006/relationships",
          "xmlns:m" => "http://schemas.openxmlformats.org/officeDocument/2006/math",
          "xmlns:v" => "urn:schemas-microsoft-com:vml",
          "xmlns:wp14" => "http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing",
          "xmlns:wp" => "http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing",
          "xmlns:w10" => "urn:schemas-microsoft-com:office:word",
          "xmlns:w" => "http://schemas.openxmlformats.org/wordprocessingml/2006/main",
          "xmlns:w14" => "http://schemas.microsoft.com/office/word/2010/wordml",
          "xmlns:wpg" => "http://schemas.microsoft.com/office/word/2010/wordprocessingGroup",
          "xmlns:wpi" => "http://schemas.microsoft.com/office/word/2010/wordprocessingInk",
          "xmlns:wne" => "http://schemas.microsoft.com/office/word/2006/wordml",
          "xmlns:wps" => "http://schemas.microsoft.com/office/word/2010/wordprocessingShape",
          "mc:Ignorable" => "w14 wp14" do |xml|
          xml.w :p do |xml|
            xml.w :pPr do |xml|
              xml.w :jc, "w:val" => "#{@align}" if @align
              xml.w :pStyle, "w:val" => "Header"
              xml.w :proofErr, "w:type" => "spellStart"
              xml.w :proofErr, "w:type" => "gramStart"
              xml.w :r do |xml|
                xml.w :t, @contents
              end
              xml.w :proofErr, "w:type" => "spellEnd"
              xml.w :proofErr, "w:type" => "gramEnd"
            end
          end
        end
      else
        xml.instruct! :xml, :version => "1.0", :encoding=>"UTF-8", :standalone => "yes"
        xml.w :ftr, "xmlns:o" => "urn:schemas-microsoft-com:office:office",
        "xmlns:r" => "http://schemas.openxmlformats.org/officeDocument/2006/relationships",
        "xmlns:v" => "urn:schemas-microsoft-com:vml",
        "xmlns:w" => "http://schemas.openxmlformats.org/wordprocessingml/2006/main",
        "xmlns:w10" => "urn:schemas-microsoft-com:office:word",
        "xmlns:wp" => "http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" do |xml|

          xml.w :p do |xml|
            xml.w :pPr do |xml|
              xml.w :jc, "w:val" => "#{@align}" if @align
            end
            if @contents == :pagenum
              xml.w :r do |xml|
                xml.w :fldChar, "w:fldCharType" => "begin"
              end
              xml.w :r do |xml|
                xml.w :instrText, "PAGE"
              end
              xml.w :r do |xml|
                xml.w :fldChar, "w:fldCharType" => "separate"
              end
              xml.w :r do |xml|
                xml.w :t, "i"
              end
              xml.w :r do |xml|
                xml.w :fldChar, "w:fldCharType" => "end"
              end
            else
              xml.w :r do |xml|
                xml.w :t, @contents
              end
            end
          end
        end
      end
  end
end

Tiếp theo ta sửa cấu trúc file document.xml, file này được generate bởi class Builder:

module Docxtor
  module Document
    class Builder
      ...
      def render(&block)
        xml = ::Builder::XmlMarkup.new

        xml.instruct! :xml, :version => "1.0", :encoding => "UTF-8", :standalone => "yes"
        xml.w :document, "xmlns:wpc" => "http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas",
          "xmlns:mo" => "http://schemas.microsoft.com/office/mac/office/2008/main",
          "xmlns:mc" => "http://schemas.openxmlformats.org/markup-compatibility/2006",
          "xmlns:mv" => "urn:schemas-microsoft-com:mac:vml",
          "xmlns:o" => "urn:schemas-microsoft-com:office:office",
          "xmlns:r" => "http://schemas.openxmlformats.org/officeDocument/2006/relationships",
          "xmlns:m" => "http://schemas.openxmlformats.org/officeDocument/2006/math",
          "xmlns:v" => "urn:schemas-microsoft-com:vml",
          "xmlns:wp14" => "http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing",
          "xmlns:wp" => "http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing",
          "xmlns:w10" => "urn:schemas-microsoft-com:office:word",
          "xmlns:w" => "http://schemas.openxmlformats.org/wordprocessingml/2006/main",
          "xmlns:w14" => "http://schemas.microsoft.com/office/word/2010/wordml",
          "xmlns:wpg" => "http://schemas.microsoft.com/office/word/2010/wordprocessingGroup",
          "xmlns:wpi" => "http://schemas.microsoft.com/office/word/2010/wordprocessingInk",
          "xmlns:wne" => "http://schemas.microsoft.com/office/word/2006/wordml",
          "xmlns:wps" => "http://schemas.microsoft.com/office/word/2010/wordprocessingShape",
          "mc:Ignorable" => "w14 wp14" do
          xml.w :body do
            xml << Document::Root.new(reference, &block).render(::Builder::XmlMarkup.new)

            render_running_elements xml
          end
        end

        xml.target!
      end
      ...
    end
  end
end

Ngoài ra, vì thêm thành phần image nên chúng ta cần khai báo thêm MIME là loại image trong [Content_Types].xml.

# file templates/default/[Content_Types].xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
  <Default Extension="xml" ContentType="application/xml"/>
  <Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/>
  <Default Extension="jpg" ContentType="image/jpeg"/>
  <Default Extension="jpeg" ContentType="image/jpeg"/>
  <Default Extension="png" ContentType="image/png"/>
  <Default Extension="gif" ContentType="image/gif"/>
  <Override PartName="/word/document.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml"/>
  <Override PartName="/word/styles.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml"/>
  <Override PartName="/word/stylesWithEffects.xml" ContentType="application/vnd.ms-word.stylesWithEffects+xml"/>
  <Override PartName="/word/settings.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml"/>
  <Override PartName="/word/webSettings.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.webSettings+xml"/>
  <Override PartName="/word/fontTable.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml"/>
  <Override PartName="/word/theme/theme1.xml" ContentType="application/vnd.openxmlformats-officedocument.theme+xml"/>
  <Override PartName="/docProps/core.xml" ContentType="application/vnd.openxmlformats-package.core-properties+xml"/>
  <Override PartName="/docProps/app.xml" ContentType="application/vnd.openxmlformats-officedocument.extended-properties+xml"/>
  <Override PartName="/word/header1.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.header+xml"/>
</Types>

Tham khảo:

http://en.wikipedia.org/wiki/Office_Open_XML_file_formats

https://msdn.microsoft.com/en-us/library/bb266220(v=office.12).aspx

Github: https://github.com/ducnhat1989/docxtor/compare/ba9091d...e53844d


All Rights Reserved