diff --git a/Changelog.md b/Changelog.md index 523c74c4..340b0e51 100644 --- a/Changelog.md +++ b/Changelog.md @@ -36,6 +36,7 @@ * `ParagraphTab` now stored in `Tabs` in `ParagraphProperties` * Add `OoxmlSize` support of `one_240th_cm` and use in `Spacing` * Add parsing `PresetColor` to `GradientStop` +* Add Parsing `NumberingLevel#suffix` ### Fixes * Fix parsing document style id - it can be string, not only digit diff --git a/lib/ooxml_parser/docx_parser/docx_data/document_structure.rb b/lib/ooxml_parser/docx_parser/docx_data/document_structure.rb index ea6c9ec2..65d132fa 100644 --- a/lib/ooxml_parser/docx_parser/docx_data/document_structure.rb +++ b/lib/ooxml_parser/docx_parser/docx_data/document_structure.rb @@ -130,7 +130,7 @@ def self.parse end parse_default_style doc_structure = DocumentStructure.new - doc_structure.numbering = Numbering.parse + doc_structure.numbering = Numbering.new(parent: doc_structure).parse doc_structure.document_styles = DocumentStyle.parse_list(doc_structure) number = 0 OOXMLDocumentObject.add_to_xmls_stack('word/document.xml') diff --git a/lib/ooxml_parser/docx_parser/docx_data/document_structure/numbering.rb b/lib/ooxml_parser/docx_parser/docx_data/document_structure/numbering.rb index fc06cf8a..b02c8614 100644 --- a/lib/ooxml_parser/docx_parser/docx_data/document_structure/numbering.rb +++ b/lib/ooxml_parser/docx_parser/docx_data/document_structure/numbering.rb @@ -8,9 +8,10 @@ class Numbering < OOXMLDocumentObject # @return [Array, NumberingDefinition] numbering definition list attr_accessor :numbering_definition_list - def initialize + def initialize(parent: nil) @abstract_numbering_list = [] @numbering_definition_list = [] + @parent = parent end def properties_by_num_id(num_id) @@ -26,20 +27,19 @@ def properties_by_num_id(num_id) end end - def self.parse - numbering = Numbering.new + def parse numbering_xml = OOXMLDocumentObject.path_to_folder + 'word/numbering.xml' return nil unless File.exist?(numbering_xml) node = Nokogiri::XML(File.open(numbering_xml), 'r:UTF-8') node.xpath('w:numbering/*').each do |numbering_child_node| case numbering_child_node.name when 'abstractNum' - numbering.abstract_numbering_list << AbstractNumbering.parse(numbering_child_node) + @abstract_numbering_list << AbstractNumbering.new(parent: self).parse(numbering_child_node) when 'num' - numbering.numbering_definition_list << NumberingDefinition.parse(numbering_child_node) + @numbering_definition_list << NumberingDefinition.new(parent: self).parse(numbering_child_node) end end - numbering + self end end end diff --git a/lib/ooxml_parser/docx_parser/docx_data/document_structure/numbering/abstract_numbering.rb b/lib/ooxml_parser/docx_parser/docx_data/document_structure/numbering/abstract_numbering.rb index 1b8f8b41..69697a13 100644 --- a/lib/ooxml_parser/docx_parser/docx_data/document_structure/numbering/abstract_numbering.rb +++ b/lib/ooxml_parser/docx_parser/docx_data/document_structure/numbering/abstract_numbering.rb @@ -4,7 +4,7 @@ module OoxmlParser # This element specifies a set of properties which shall dictate the appearance and # behavior of a set of numbered # paragraphs in a WordprocessingML document. - class AbstractNumbering + class AbstractNumbering < OOXMLDocumentObject # @return [Integer] abstruct numbering id attr_accessor :id # @return [MultilevelType] myltylevel type @@ -12,32 +12,31 @@ class AbstractNumbering # @return [Array, NumberingLevel] numbering level data list attr_accessor :level_list - def initialize + def initialize(parent: nil) @level_list = [] + @parent = parent end # Parse Abstract Numbering data # @param [Nokogiri::XML:Element] node with Abstract Numbering data # @return [AbstractNumbering] value of Abstract Numbering data - def self.parse(node) - abstract_numbering = AbstractNumbering.new - + def parse(node) node.attributes.each do |key, value| case key when 'abstractNumId' - abstract_numbering.id = value.value.to_f + @id = value.value.to_f end end node.xpath('*').each do |numbering_child_node| case numbering_child_node.name when 'multiLevelType' - abstract_numbering.multilevel_type = MultilevelType.new(parent: abstract_numbering).parse(numbering_child_node) + @multilevel_type = MultilevelType.new(parent: self).parse(numbering_child_node) when 'lvl' - abstract_numbering.level_list << NumberingLevel.parse(numbering_child_node) + @level_list << NumberingLevel.new(parent: self).parse(numbering_child_node) end end - abstract_numbering + self end end end diff --git a/lib/ooxml_parser/docx_parser/docx_data/document_structure/numbering/abstract_numbering/numbering_level.rb b/lib/ooxml_parser/docx_parser/docx_data/document_structure/numbering/abstract_numbering/numbering_level.rb index 65ef402a..955d2739 100644 --- a/lib/ooxml_parser/docx_parser/docx_data/document_structure/numbering/abstract_numbering/numbering_level.rb +++ b/lib/ooxml_parser/docx_parser/docx_data/document_structure/numbering/abstract_numbering/numbering_level.rb @@ -2,10 +2,11 @@ require_relative 'numbering_level/level_text' require_relative 'numbering_level/numbering_format' require_relative 'numbering_level/start' +require_relative 'numbering_level/suffix' module OoxmlParser # This element specifies the appearance and behavior of a numbering level # within a given abstract numbering - class NumberingLevel + class NumberingLevel < OOXMLDocumentObject # @return [Integer] level id attr_accessor :ilvl # @return [Start] start data @@ -20,38 +21,45 @@ class NumberingLevel attr_accessor :paragraph_properties # @return [RunProperties] properties of run attr_accessor :run_properties + # @return [Suffix] value of Suffix + attr_accessor :suffix + + def initialize(parent: nil) + @parent = parent + @suffix = Suffix.new(parent: self) + end # Parse Numbering Level data # @param [Nokogiri::XML:Element] node with Numbering Level data # @return [NumberingLevel] value of Numbering Level data - def self.parse(node) - level = NumberingLevel.new - + def parse(node) node.attributes.each do |key, value| case key when 'ilvl' - level.ilvl = value.value.to_f + @ilvl = value.value.to_f end end node.xpath('*').each do |num_level_child| case num_level_child.name when 'start' - level.start = Start.parse(num_level_child) + @start = Start.parse(num_level_child) when 'numFmt' - level.numbering_format = NumberingFormat.parse(num_level_child) + @numbering_format = NumberingFormat.parse(num_level_child) when 'lvlText' - level.text = LevelText.parse(num_level_child) + @text = LevelText.parse(num_level_child) when 'lvlJc' - level.justification = LevelJustification.parse(num_level_child) + @justification = LevelJustification.parse(num_level_child) when 'pPr' - level.paragraph_properties = ParagraphProperties.new(parent: level).parse(num_level_child) + @paragraph_properties = ParagraphProperties.new(parent: self).parse(num_level_child) when 'rPr' - level.run_properties = RunProperties.new(parent: level).parse(num_level_child) + @run_properties = RunProperties.new(parent: self).parse(num_level_child) + when 'suff' + @suffix = @suffix.parse(num_level_child) end end - level + self end end end diff --git a/lib/ooxml_parser/docx_parser/docx_data/document_structure/numbering/abstract_numbering/numbering_level/suffix.rb b/lib/ooxml_parser/docx_parser/docx_data/document_structure/numbering/abstract_numbering/numbering_level/suffix.rb new file mode 100644 index 00000000..f385b8ba --- /dev/null +++ b/lib/ooxml_parser/docx_parser/docx_data/document_structure/numbering/abstract_numbering/numbering_level/suffix.rb @@ -0,0 +1,31 @@ +module OoxmlParser + # Class for storing Suffix `w:suff` + # This element specifies the content which + # shall be added between a given numbering level's text and the text of + # every numbered paragraph which references that numbering level. + # If this element is omitted, then its value shall be assumed to be tab. + # >ECMA-376, 3rd Edition (June, 2011), Fundamentals and Markup Language Reference 17.9.29. + class Suffix < OOXMLDocumentObject + # @return [String] value of suffix + attr_accessor :value + + def initialize(value = :tab, + parent: nil) + @value = value + @parent = parent + end + + # Parse Suffix + # @param [Nokogiri::XML:Node] node with Suffix + # @return [Suffix] result of parsing + def parse(node) + node.attributes.each do |key, value| + case key + when 'val' + @value = value.value.to_sym + end + end + self + end + end +end diff --git a/lib/ooxml_parser/docx_parser/docx_data/document_structure/numbering/numbering_definition.rb b/lib/ooxml_parser/docx_parser/docx_data/document_structure/numbering/numbering_definition.rb index b10ffe63..02ac5f6e 100644 --- a/lib/ooxml_parser/docx_parser/docx_data/document_structure/numbering/numbering_definition.rb +++ b/lib/ooxml_parser/docx_parser/docx_data/document_structure/numbering/numbering_definition.rb @@ -2,7 +2,7 @@ module OoxmlParser # This element specifies a unique instance of numbering information that can be referenced by zero or more # paragraphs within the parent WordprocessingML document. - class NumberingDefinition + class NumberingDefinition < OOXMLDocumentObject # @return [Integer] num id attr_accessor :id # @return [AbstractNumberingId] abstract numbering id @@ -11,23 +11,21 @@ class NumberingDefinition # Parse NumberingDefinition data # @param [Nokogiri::XML:Element] node with NumberingDefinition data # @return [NumberingDefinition] value of Abstract Numbering data - def self.parse(node) - num = NumberingDefinition.new - + def parse(node) node.attributes.each do |key, value| case key when 'numId' - num.id = value.value.to_f + @id = value.value.to_f end end node.xpath('*').each do |numbering_child_node| case numbering_child_node.name when 'abstractNumId' - num.abstract_numbering_id = AbstractNumberingId.parse(numbering_child_node) + @abstract_numbering_id = AbstractNumberingId.new(parent: self).parse(numbering_child_node) end end - num + self end end end diff --git a/lib/ooxml_parser/docx_parser/docx_data/document_structure/numbering/numbering_definition/abstract_numbering_id.rb b/lib/ooxml_parser/docx_parser/docx_data/document_structure/numbering/numbering_definition/abstract_numbering_id.rb index 52b0fbcc..51f51b47 100644 --- a/lib/ooxml_parser/docx_parser/docx_data/document_structure/numbering/numbering_definition/abstract_numbering_id.rb +++ b/lib/ooxml_parser/docx_parser/docx_data/document_structure/numbering/numbering_definition/abstract_numbering_id.rb @@ -1,22 +1,20 @@ module OoxmlParser # Class for storing AbstractNumberingId - class AbstractNumberingId + class AbstractNumberingId < OOXMLDocumentObject # @return [String] value of start attr_accessor :value # Parse AbstractNumberingId # @param [Nokogiri::XML:Node] node with AbstractNumberingId # @return [AbstractNumberingId] result of parsing - def self.parse(node) - abstract_id = AbstractNumberingId.new - + def parse(node) node.attributes.each do |key, value| case key when 'val' - abstract_id.value = value.value.to_i + @value = value.value.to_i end end - abstract_id + self end end end diff --git a/spec/document/elements/paragraph/numbering/numbering_suffix.docx b/spec/document/elements/paragraph/numbering/numbering_suffix.docx new file mode 100644 index 00000000..6a86ac8d Binary files /dev/null and b/spec/document/elements/paragraph/numbering/numbering_suffix.docx differ diff --git a/spec/document/elements/paragraph/numbering_spec.rb b/spec/document/elements/paragraph/numbering_spec.rb index 98bcb74b..5c656bd2 100644 --- a/spec/document/elements/paragraph/numbering_spec.rb +++ b/spec/document/elements/paragraph/numbering_spec.rb @@ -41,4 +41,9 @@ docx = OoxmlParser::DocxParser.parse_docx('spec/document/elements/paragraph/numbering/numbering_in_table.docx') expect(docx.element_by_description(location: :canvas, type: :table).first.numbering.abstruct_numbering.level_list.first.text.value).to eq('ยจ') end + + it 'numbering_suffix' do + docx = OoxmlParser::Parser.parse('spec/document/elements/paragraph/numbering/numbering_suffix.docx') + expect(docx.element_by_description.first.numbering.abstruct_numbering.level_list.first.suffix.value).to eq(:space) + end end