mirror of
https://github.com/pgbackrest/pgbackrest.git
synced 2025-01-30 05:39:12 +02:00
Add new XML functions required for building documentation.
This commit is contained in:
parent
8f319b6fd3
commit
217584a2c4
@ -4,6 +4,31 @@ XML Handler Extensions
|
|||||||
// Include core module
|
// Include core module
|
||||||
#include "common/type/xml.c"
|
#include "common/type/xml.c"
|
||||||
|
|
||||||
|
#include "build/common/xml.h"
|
||||||
|
|
||||||
|
/**********************************************************************************************************************************/
|
||||||
|
XmlDocument *
|
||||||
|
xmlDocumentNewParam(const String *const rootNode, const XmlDocumentNewParam param)
|
||||||
|
{
|
||||||
|
FUNCTION_TEST_BEGIN();
|
||||||
|
FUNCTION_TEST_PARAM(STRING, rootNode);
|
||||||
|
FUNCTION_TEST_PARAM(STRING, param.dtdName);
|
||||||
|
FUNCTION_TEST_PARAM(STRING, param.dtdFile);
|
||||||
|
FUNCTION_TEST_END();
|
||||||
|
|
||||||
|
ASSERT(rootNode != NULL);
|
||||||
|
|
||||||
|
XmlDocument *const result = xmlDocumentNew(rootNode);
|
||||||
|
|
||||||
|
if (param.dtdName != NULL)
|
||||||
|
{
|
||||||
|
ASSERT(param.dtdFile != NULL);
|
||||||
|
xmlCreateIntSubset(result->xml, (unsigned char *)strZ(param.dtdName), NULL, (unsigned char *)strZ(param.dtdFile));
|
||||||
|
}
|
||||||
|
|
||||||
|
FUNCTION_TEST_RETURN(XML_DOCUMENT, result);
|
||||||
|
}
|
||||||
|
|
||||||
/**********************************************************************************************************************************/
|
/**********************************************************************************************************************************/
|
||||||
String *
|
String *
|
||||||
xmlNodeAttribute(const XmlNode *this, const String *name)
|
xmlNodeAttribute(const XmlNode *this, const String *name)
|
||||||
@ -27,3 +52,74 @@ xmlNodeAttribute(const XmlNode *this, const String *name)
|
|||||||
|
|
||||||
FUNCTION_TEST_RETURN(STRING, result);
|
FUNCTION_TEST_RETURN(STRING, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**********************************************************************************************************************************/
|
||||||
|
void
|
||||||
|
xmlNodeAttributeSet(XmlNode *const this, const String *const name, const String *const value)
|
||||||
|
{
|
||||||
|
FUNCTION_TEST_BEGIN();
|
||||||
|
FUNCTION_TEST_PARAM(XML_NODE, this);
|
||||||
|
FUNCTION_TEST_PARAM(STRING, name);
|
||||||
|
FUNCTION_TEST_PARAM(STRING, value);
|
||||||
|
FUNCTION_TEST_END();
|
||||||
|
|
||||||
|
ASSERT(this != NULL);
|
||||||
|
ASSERT(name != NULL);
|
||||||
|
ASSERT(value != NULL);
|
||||||
|
|
||||||
|
xmlSetProp(this->node, (unsigned char *)strZ(name), (unsigned char *)strZ(value));
|
||||||
|
|
||||||
|
FUNCTION_TEST_RETURN_VOID();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************************************************************************************************************************/
|
||||||
|
void
|
||||||
|
xmlNodeChildAdd(XmlNode *const this, const XmlNode *const child)
|
||||||
|
{
|
||||||
|
FUNCTION_TEST_BEGIN();
|
||||||
|
FUNCTION_TEST_PARAM(XML_NODE, this);
|
||||||
|
FUNCTION_TEST_PARAM(XML_NODE, child);
|
||||||
|
FUNCTION_TEST_END();
|
||||||
|
|
||||||
|
ASSERT(this != NULL);
|
||||||
|
ASSERT(child != NULL);
|
||||||
|
|
||||||
|
MEM_CONTEXT_TEMP_BEGIN()
|
||||||
|
{
|
||||||
|
for (xmlNodePtr currentNodeRaw = child->node->children; currentNodeRaw != NULL; currentNodeRaw = currentNodeRaw->next)
|
||||||
|
{
|
||||||
|
// Skip comments
|
||||||
|
if (currentNodeRaw->type == XML_COMMENT_NODE)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Copy all child nodes (only node and text types are copied)
|
||||||
|
XmlNode *const currentNode = xmlNodeNew(currentNodeRaw);
|
||||||
|
|
||||||
|
if (currentNode->node->type == XML_ELEMENT_NODE)
|
||||||
|
{
|
||||||
|
XmlNode *const node = xmlNodeAdd(this, STR((char *)currentNode->node->name));
|
||||||
|
|
||||||
|
// Copy node attributes
|
||||||
|
for (xmlAttrPtr currentAttr = currentNode->node->properties; currentAttr != NULL; currentAttr = currentAttr->next)
|
||||||
|
{
|
||||||
|
xmlNodeAttributeSet(
|
||||||
|
node, STR((char *)currentAttr->name), xmlNodeAttribute(currentNode, STR((char *)currentAttr->name)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Recurse to copy child nodes
|
||||||
|
xmlNodeChildAdd(node, currentNode);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CHECK_FMT(
|
||||||
|
AssertError, currentNode->node->type == XML_TEXT_NODE, "unknown type %u in node '%s'", currentNode->node->type,
|
||||||
|
(char *)currentNode->node->name);
|
||||||
|
|
||||||
|
xmlNodeContentSet(this, xmlNodeContent(currentNode));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MEM_CONTEXT_TEMP_END();
|
||||||
|
|
||||||
|
FUNCTION_TEST_RETURN_VOID();
|
||||||
|
}
|
||||||
|
@ -6,10 +6,32 @@ XML Handler Extensions
|
|||||||
|
|
||||||
#include "common/type/xml.h"
|
#include "common/type/xml.h"
|
||||||
|
|
||||||
|
/***********************************************************************************************************************************
|
||||||
|
Constructors
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
typedef struct XmlDocumentNewParam
|
||||||
|
{
|
||||||
|
VAR_PARAM_HEADER;
|
||||||
|
const String *dtdName; // DTD name, if any
|
||||||
|
const String *dtdFile; // DTD file (must be set if dtdName is set)
|
||||||
|
} XmlDocumentNewParam;
|
||||||
|
|
||||||
|
#define xmlDocumentNewP(rootNode, ...) \
|
||||||
|
xmlDocumentNewParam(rootNode, (XmlDocumentNewParam){VAR_PARAM_INIT, __VA_ARGS__})
|
||||||
|
|
||||||
|
XmlDocument *xmlDocumentNewParam(const String *rootNode, XmlDocumentNewParam param);
|
||||||
|
|
||||||
/***********************************************************************************************************************************
|
/***********************************************************************************************************************************
|
||||||
Node Getters/Setters
|
Node Getters/Setters
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
// Node attribute
|
// Get/set node attribute
|
||||||
String *xmlNodeAttribute(const XmlNode *this, const String *name);
|
String *xmlNodeAttribute(const XmlNode *this, const String *name);
|
||||||
|
void xmlNodeAttributeSet(XmlNode *this, const String *name, const String *value);
|
||||||
|
|
||||||
|
/***********************************************************************************************************************************
|
||||||
|
Functions
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
// Add all child nodes to another node
|
||||||
|
void xmlNodeChildAdd(XmlNode *this, const XmlNode *child);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -84,7 +84,7 @@ testRun(void)
|
|||||||
|
|
||||||
// Create an empty document, add data to it, and output xml
|
// Create an empty document, add data to it, and output xml
|
||||||
// -------------------------------------------------------------------------------------------------------------------------
|
// -------------------------------------------------------------------------------------------------------------------------
|
||||||
TEST_ASSIGN(xmlDocument, xmlDocumentNew(STRDEF("CompleteMultipartUpload")), "new xml with root node");
|
TEST_ASSIGN(xmlDocument, xmlDocumentNewP(STRDEF("CompleteMultipartUpload")), "new xml with root node");
|
||||||
|
|
||||||
XmlNode *partNode = NULL;
|
XmlNode *partNode = NULL;
|
||||||
TEST_ASSIGN(partNode, xmlNodeAdd(xmlDocumentRoot(xmlDocument), STRDEF("Part")), "create part node 1");
|
TEST_ASSIGN(partNode, xmlNodeAdd(xmlDocumentRoot(xmlDocument), STRDEF("Part")), "create part node 1");
|
||||||
@ -103,6 +103,38 @@ testRun(void)
|
|||||||
"<Part><PartNumber>2</PartNumber><ETag>E2</ETag></Part>"
|
"<Part><PartNumber>2</PartNumber><ETag>E2</ETag></Part>"
|
||||||
"</CompleteMultipartUpload>\n",
|
"</CompleteMultipartUpload>\n",
|
||||||
"get xml");
|
"get xml");
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------------------------------------------------------
|
||||||
|
TEST_TITLE("copy xml between documents");
|
||||||
|
|
||||||
|
XmlDocument *xmlDocument2 = NULL;
|
||||||
|
|
||||||
|
TEST_ASSIGN(
|
||||||
|
xmlDocument, xmlDocumentNewP(STRDEF("doc1"), .dtdName = STRDEF("doc"), .dtdFile = STRDEF("doc.dtd")),
|
||||||
|
"new xml with dtd");
|
||||||
|
TEST_ASSIGN(
|
||||||
|
xmlDocument2,
|
||||||
|
xmlDocumentNewBuf(
|
||||||
|
BUFSTRDEF(
|
||||||
|
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
||||||
|
"<doc2>\n"
|
||||||
|
" <!-- comment -->\n"
|
||||||
|
" text55\n"
|
||||||
|
" <name id=\"id55\">name55</name>\n"
|
||||||
|
"</doc2>")),
|
||||||
|
"valid xml");
|
||||||
|
|
||||||
|
TEST_RESULT_VOID(xmlNodeChildAdd(xmlDocumentRoot(xmlDocument), xmlDocumentRoot(xmlDocument2)), "copy xml");
|
||||||
|
TEST_RESULT_STR_Z(
|
||||||
|
strNewBuf(xmlDocumentBuf(xmlDocument)),
|
||||||
|
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
||||||
|
"<!DOCTYPE doc SYSTEM \"doc.dtd\">\n"
|
||||||
|
"<doc1>\n"
|
||||||
|
" \n"
|
||||||
|
" text55\n"
|
||||||
|
" <name id=\"id55\">name55</name>\n"
|
||||||
|
"</doc1>\n",
|
||||||
|
"get xml");
|
||||||
}
|
}
|
||||||
|
|
||||||
FUNCTION_HARNESS_RETURN_VOID();
|
FUNCTION_HARNESS_RETURN_VOID();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user