1
0
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:
David Steele 2023-09-29 16:52:08 -04:00
parent 8f319b6fd3
commit 217584a2c4
3 changed files with 152 additions and 2 deletions

View File

@ -4,6 +4,31 @@ XML Handler Extensions
// Include core module
#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 *
xmlNodeAttribute(const XmlNode *this, const String *name)
@ -27,3 +52,74 @@ xmlNodeAttribute(const XmlNode *this, const String *name)
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();
}

View File

@ -6,10 +6,32 @@ XML Handler Extensions
#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 attribute
// Get/set node attribute
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

View File

@ -84,7 +84,7 @@ testRun(void)
// 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;
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>"
"</CompleteMultipartUpload>\n",
"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();