#ifndef DYNAMIC_DEPTH_INTERNAL_XMPMETA_XML_SERIALIZER_IMPL_H_ // NOLINT #define DYNAMIC_DEPTH_INTERNAL_XMPMETA_XML_SERIALIZER_IMPL_H_ // NOLINT #include #include #include #include "xmpmeta/xml/serializer.h" namespace dynamic_depth { namespace xmpmeta { namespace xml { // Writes properties, lists, and child nodes into an XML structure. // // Usage example: // std::unordered_map namespaces; // string device_name("Device"); // string cameras_name("Cameras"); // string camera_name("Camera"); // string audio_name("Audio"); // string image_name("Image"); // PopulateNamespaces(&namespaces); // DoSerialization(); // // // Serialization example. // void DoSerialization() { // xmlNodePtr device_node = xmlNewNode(nullptr, device_name); // Serializer device_serializer(namespaces, device_node); // // std::unique_ptr cameras_serializer = // serializer->CreateListSerializer(cameras_name); // for (XdmCamera *camera : camera_list_) { // std::unique_ptr camera_serializer = // cameras_serializer->CreateItemSerializer("Device", camera_name); // success &= camera->Serialize(camera_serializer.get()); // // // Serialize Audio. // std::unique_ptr audio_serializer = // camera_serializer->CreateSerializer("Camera", audio_name); // audio_serializer->WriteProperty(camera_name, "Data", audio_data); // audio_serializer->WriteProperty(camera_name, "Mime", "audio/mp4"); // // // Serialize Image. // std::unique_ptr image_serializer = // camera_serializer->CreateSerializer("Camera", image_name); // image_serializer->WriteProperty(image_name, "Data", image_data); // image_serializer->WriteProperty(image_name, "Mime", "image/jpeg"); // // // Serialize ImagingModel. // std::unique_ptr imaging_model_serializer = // camera_serializer->CreateSerializer("Camera", "ImagingModel"); // std::unique_ptr equirect_model_serializer = // imaging_model_serializer->CreateSerializer("Camera", // "EquirectModel"); // // Serializer equirect model fields here. // } // } // // Resulting XML structure: // /* // * // * // * // * // * // * // * // * // * // * // * // * // * // * // * // */ // // // Namespace population example. // void PopulateNamespaces(std::unordered_map* namespaces) { // xmlNsPtr device_ns = // xmlNewNs(nullptr, ToXmlChar("http://ns.xdm.org/photos/1.0/device") // ToXmlChar(device_name.data())); // xmlNsPtr camera_ns = // xmlNewNs(nullptr, ToXmlChar("http://ns.xdm.org/photos/1.0/camera") // ToXmlChar(camera_name.data())); // xmlNsPtr audio_ns = // xmlNewNs(nullptr, ToXmlChar("http://ns.xdm.org/photos/1.0/audio") // ToXmlChar(audio_name.data())); // xmlNsPtr image_ns = // xmlNewNs(nullptr, ToXmlChar("http://ns.xdm.org/photos/1.0/image") // ToXmlChar(image_name.data())); // namespaces->insert(device_name, device_ns); // namespaces->insert(camera_name, camera_ns); // namespaces->insert(audio_name, audio_ns); // namespaces->insert(image_name, image_ns); // } class SerializerImpl : public Serializer { public: // Constructor. // The prefix map is required if one of the CreateSerializer methods will be // called on this object. In particular, the RDF namespace must be present in // the prefix map if CreateItemSerializer or CreateListSerializer will be // called. // The namespaces map serves to keep XML namespace creation out of this // Serializer, to simplify memory management issues. Note that the libxml // xmlDocPtr will own all namespace and node pointers. // The namespaces parameter is a map of node names to full namespaces. // This contains all the namespaces (nodes and properties) that will be used // in serialization. // The node parameter is the caller node. This will be the node in which // serialization takes place in WriteProperties. SerializerImpl(const std::unordered_map& namespaces, xmlNodePtr node); // Returns a new Serializer for an object that is part of an rdf:Seq list // of objects. // The parent serializer must be created with CreateListSerializer. std::unique_ptr CreateItemSerializer( const string& prefix, const string& item_name) const override; // Returns a new Serializer for a list of objects that correspond to an // rdf:Seq XML node, where each object is to be serialized as a child node of // every rdf:li node in the list. // The serializer is created on an rdf:Seq node, which is the child of a // newly created XML node with the name list_name. std::unique_ptr CreateListSerializer( const string& prefix, const string& list_name) const override; // Creates a serializer from the current serializer. // @param node_name The name of the caller node. This will be the parent of // any new nodes or properties set by this serializer. std::unique_ptr CreateSerializer( const string& node_ns_name, const string& node_name) const override; // Writes the property into the current node, prefixed with prefix if it // has a corresponding namespace href in namespaces_, fails otherwise. // Returns true if serialization is successful. // If prefix is empty, the property will not be set on an XML namespace. // name must not be empty. // value may be empty. bool WriteBoolProperty(const string& prefix, const string& name, bool value) const override; bool WriteProperty(const string& prefix, const string& name, const string& value) const override; // Writes the collection of numbers into a child rdf:Seq node. bool WriteIntArray(const string& prefix, const string& array_name, const std::vector& values) const override; bool WriteDoubleArray(const string& prefix, const string& array_name, const std::vector& values) const override; // Class-specific methods. // Constructs a serializer object and writes the xmlNsPtr objects in // namespaces_ to node_. static std::unique_ptr FromDataAndSerializeNamespaces( const std::unordered_map& namespaces, xmlNodePtr node); // Disallow copying. SerializerImpl(const SerializerImpl&) = delete; void operator=(const SerializerImpl&) = delete; private: // Writes the xmlNsPtr objects in namespaces_ to node_. // Modifies namespaces_ by setting each xmlNsPtr's next pointer to the // subsequent entry in the collection. bool SerializeNamespaces(); xmlNodePtr node_; std::unordered_map namespaces_; }; } // namespace xml } // namespace xmpmeta } // namespace dynamic_depth #endif // DYNAMIC_DEPTH_INTERNAL_XMPMETA_XML_SERIALIZER_IMPL_H_ // NOLINT