Developer Guide
===============
Before Starting
---------------
Before using NoMETA as a developer, you should be familiar with the Office Open XML (OOXML) properties defined in `ECMA-376 `_.
So, you can understand the Microsoft implementation of *app.xml* and *core.xml* in *docProps* folder structure.
Introduction
------------
The main class of NoMETA is :class:`Document `, it's responsible for opening and saving MS Office documents. It also agregates two classes, :class:`App ` and :class:`Core `, to deal with XML tag values.
In context of NoMETA, ``App`` and ``Core`` are sheets that represents the XML files *docProps/app.xml* and *docProps/core.xml*, respectively. These classes have properties to deal with the most popular tags of each file.
By convention, each property has the same name of the corresponding XML tag in **snake_case** format (eg. ```` is :attr:`last_modified_by `)
So, you can edit these properties and save a new version of the document like in the code snippet below:
.. code-block:: python
:linenos:
from nometa import Document, Core, App
doc = Document("tests/resource/test.docx",Core,App)
doc.core.creator = "Johnny Test"
doc.save("test2.docx")
|
.. tip::
The constructor of Document class can accept, as first parameter, a string (which is the file path) or an in-memory buffer of bytes.
The ``save`` method behaves similarly.
See the class documentation for more details.
|
How to handle a new XML tag?
----------------------------
If ``App`` or ``Core`` classes don't handle some XML tag, you can extend them in order to handle the specific tag. As an example, suppose that a new tag called **dc:unreal** is present in *docProps/core.xml*, so you could access it as following:
.. code-block:: python
:linenos:
:emphasize-lines: 8,12
from nometa import *
from typing import cast
from nometa.properties.text import TextProperty
class UnrealCore(Core):
def __init__(self, raw) -> None:
super().__init__(raw)
self._unreal=TextProperty.from_element("dc:unreal", self._xml_root)
def to_element(self) -> None:
super().to_element()
self._unreal.to_element(self._xml_root)
@property
def unreal(self) -> str|None:
return self._unreal.value
@unreal.setter
def unreal(self, val: str) -> None:
self._unreal.value=val
doc=Document("tests/resource/test.xlsx",UnrealCore,App)
ucore=cast(UnrealCore, doc.core)
print(ucore.unreal)
The attribute ``_xml_root`` of :class:`nometa.sheet.Sheet` class keeps an instance of ``etree._Element`` class, and you must *read from* and *write to* it. Like above in lines 8 and 12.