|
Packit |
857059 |
/* BEGIN_ICS_COPYRIGHT7 ****************************************
|
|
Packit |
857059 |
|
|
Packit |
857059 |
Copyright (c) 2015-2017, Intel Corporation
|
|
Packit |
857059 |
|
|
Packit |
857059 |
Redistribution and use in source and binary forms, with or without
|
|
Packit |
857059 |
modification, are permitted provided that the following conditions are met:
|
|
Packit |
857059 |
|
|
Packit |
857059 |
* Redistributions of source code must retain the above copyright notice,
|
|
Packit |
857059 |
this list of conditions and the following disclaimer.
|
|
Packit |
857059 |
* Redistributions in binary form must reproduce the above copyright
|
|
Packit |
857059 |
notice, this list of conditions and the following disclaimer in the
|
|
Packit |
857059 |
documentation and/or other materials provided with the distribution.
|
|
Packit |
857059 |
* Neither the name of Intel Corporation nor the names of its contributors
|
|
Packit |
857059 |
may be used to endorse or promote products derived from this software
|
|
Packit |
857059 |
without specific prior written permission.
|
|
Packit |
857059 |
|
|
Packit |
857059 |
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
Packit |
857059 |
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
Packit |
857059 |
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
Packit |
857059 |
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
|
Packit |
857059 |
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
Packit |
857059 |
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
Packit |
857059 |
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
Packit |
857059 |
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
Packit |
857059 |
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
Packit |
857059 |
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
Packit |
857059 |
|
|
Packit |
857059 |
** END_ICS_COPYRIGHT7 ****************************************/
|
|
Packit |
857059 |
|
|
Packit |
857059 |
/* [ICS VERSION STRING: unknown] */
|
|
Packit |
857059 |
|
|
Packit |
857059 |
|
|
Packit |
857059 |
/*******************************************************************************
|
|
Packit |
857059 |
*
|
|
Packit |
857059 |
* File: opaxmlextract.c
|
|
Packit |
857059 |
*
|
|
Packit |
857059 |
* Description:
|
|
Packit |
857059 |
* This file implements the opaxmlextract program. opaxmlextract takes
|
|
Packit |
857059 |
* well-formed XML as input, extracts element values as specified by user
|
|
Packit |
857059 |
* input, and outputs data as lines (records) of data in CSV format.
|
|
Packit |
857059 |
*
|
|
Packit |
857059 |
* opaxmlextract uses XML Lib to parse the XML. It uses the folowing library
|
|
Packit |
857059 |
* functions:
|
|
Packit |
857059 |
* IXmlParseFile()
|
|
Packit |
857059 |
*
|
|
Packit |
857059 |
* opaxmlextract implements the following call-backs (handlers):
|
|
Packit |
857059 |
* IXML_START_TAG_FUNC()
|
|
Packit |
857059 |
* IXML_END_TAG_FUNC()
|
|
Packit |
857059 |
*
|
|
Packit |
857059 |
* opaxmlextract takes 2 types of element names as input from the user - elements
|
|
Packit |
857059 |
* to be extracted, and those for which extraction is to be suppressed. Both
|
|
Packit |
857059 |
* types of elements are stored in the Element Table (tbElements[]). As
|
|
Packit |
857059 |
* opaxmlextract processes the XML (through the call-backs), it saves the values
|
|
Packit |
857059 |
* of elements to be extracted. opaxmlextract outputs a record containing those
|
|
Packit |
857059 |
* values under the following conditions:
|
|
Packit |
857059 |
* 1 or more elements being extracted and containing a non-null value go out
|
|
Packit |
857059 |
* of scope (the element containing those elements is ended)
|
|
Packit |
857059 |
* An element changes value while it is in scope
|
|
Packit |
857059 |
*
|
|
Packit |
857059 |
* During operation, opaxmlextract maintains the hierarchical "level" at which
|
|
Packit |
857059 |
* it is extracting (top-most level is 1). Each nested element increases the
|
|
Packit |
857059 |
* level by 1. opaxmlextract performs extraction on a (specified) element
|
|
Packit |
857059 |
* regardless of the level at which the element is found.
|
|
Packit |
857059 |
*
|
|
Packit |
857059 |
* When an element is specified for suppression then no extraction will be
|
|
Packit |
857059 |
* performed during the extent of that element (begin through end).
|
|
Packit |
857059 |
* Suppression is maintained for elements specified inside the suppressed
|
|
Packit |
857059 |
* element, even if those elements have extraction specified. Suppressed
|
|
Packit |
857059 |
* elements can be nested - opaxmlextract will resume extraction after the
|
|
Packit |
857059 |
* outermost suppressed element is ended.
|
|
Packit |
857059 |
*
|
|
Packit |
857059 |
* Element names for extraction or suppression can be made context sensitive
|
|
Packit |
857059 |
* with an enclosing element name using syntax 'elem1.elem2'. elem2 will
|
|
Packit |
857059 |
* be extracted (or extraction will be suppressed) when elem2 is enclosed
|
|
Packit |
857059 |
* by elem1. The wildcard handling capability of XML Lib allows '*' to
|
|
Packit |
857059 |
* be specified as all or part of an element name. The following are valid:
|
|
Packit |
857059 |
* *.elem3 - elem3 enclosed by any sequence of elements
|
|
Packit |
857059 |
* (elem1.elem3 or elem1.elem2.elem3)
|
|
Packit |
857059 |
* elem1.*.elem3 - elem3 enclosed by elem1 with any number of (but at
|
|
Packit |
857059 |
* least 1) intermediate elements.
|
|
Packit |
857059 |
*
|
|
Packit |
857059 |
* opaxmlextract prepends any entered element name not containing '*'
|
|
Packit |
857059 |
* (anywhere) with '*.'.
|
|
Packit |
857059 |
*
|
|
Packit |
857059 |
* NOTES:
|
|
Packit |
857059 |
* opaxmlextract performs extraction using XML Lib without maintaining
|
|
Packit |
857059 |
* its own stack of elements or element values. Therefore it has the
|
|
Packit |
857059 |
* following characteristics:
|
|
Packit |
857059 |
* Enclosing elements cannot contain values;
|
|
Packit |
857059 |
*
|
|
Packit |
857059 |
* If an element name specification is such that the element can be
|
|
Packit |
857059 |
* extracted at multiple levels within the same context (enclosing
|
|
Packit |
857059 |
* element), then when the inner-most element specification ends,
|
|
Packit |
857059 |
* the element value becomes null (it does not revert to the outer
|
|
Packit |
857059 |
* value).
|
|
Packit |
857059 |
*/
|
|
Packit |
857059 |
|
|
Packit |
857059 |
|
|
Packit |
857059 |
/*******************************************************************************
|
|
Packit |
857059 |
*
|
|
Packit |
857059 |
* INCLUDES
|
|
Packit |
857059 |
*/
|
|
Packit |
857059 |
|
|
Packit |
857059 |
#include <stddef.h>
|
|
Packit |
857059 |
#include <stdio.h>
|
|
Packit |
857059 |
#include <stdlib.h>
|
|
Packit |
857059 |
#include <unistd.h>
|
|
Packit |
857059 |
#include <string.h>
|
|
Packit |
857059 |
#include <iba/ipublic.h>
|
|
Packit |
857059 |
#include <getopt.h>
|
|
Packit |
857059 |
#include "ixml.h"
|
|
Packit |
857059 |
#include "fnmatch.h"
|
|
Packit |
857059 |
|
|
Packit |
857059 |
|
|
Packit |
857059 |
/*******************************************************************************
|
|
Packit |
857059 |
*
|
|
Packit |
857059 |
* DEFINES
|
|
Packit |
857059 |
*/
|
|
Packit |
857059 |
#define ALLOW_MULTI_MATCH 1 // allow 1 tag to match mult elements
|
|
Packit |
857059 |
#define SUPPRESS_AND_EXTRACT 0 // allow 1 tag to suppress and extract
|
|
Packit |
857059 |
// this option not fully implemented
|
|
Packit |
857059 |
// procElementEnd would need more work
|
|
Packit |
857059 |
|
|
Packit |
857059 |
#define OK 0
|
|
Packit |
857059 |
#define ERROR (-1)
|
|
Packit |
857059 |
|
|
Packit |
857059 |
#define NAME_PROG "opaxmlextract" // Program name
|
|
Packit |
857059 |
#define MAX_PARAMS_FILE 512 // Max number of param file parameters
|
|
Packit |
857059 |
#define MAX_ELEMENTS 100 // Max number of elements parsable
|
|
Packit |
857059 |
#define MAX_LEVEL_PARSE MAX_ELEMENTS // Max parsing level
|
|
Packit |
857059 |
#define MAX_DELIMIT_CHARS 16 // Max size of delimiter string
|
|
Packit |
857059 |
#define MAX_INPUT_BUF 8192 // Max size of input buffer
|
|
Packit |
857059 |
#define MAX_PARAM_BUF 8192 // Max size of parameter file
|
|
Packit |
857059 |
#define MAX_FILENAME_CHARS 256 // Max size of file name
|
|
Packit |
857059 |
#define WHITE_SPACE " \t\r\n" // White space characters
|
|
Packit |
857059 |
#define OPTION_LEN 2 // string length of an option(eg. -P)
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// Element table entry, elements selected by user and present parsed value
|
|
Packit |
857059 |
typedef struct
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
char *pName; // Element name
|
|
Packit |
857059 |
char *pAttrName; // optional Attribute Name
|
|
Packit |
857059 |
char *pAttrValue; // optional Attribute Value
|
|
Packit |
857059 |
int lenValue; // Length of element value
|
|
Packit |
857059 |
// < 0 : pValue alloc'd but not in use
|
|
Packit |
857059 |
char *pValue; // Element value
|
|
Packit |
857059 |
int flags; // Flags (see ELEM_xxx below)
|
|
Packit |
857059 |
int level; // Element nesting level (0 - not open)
|
|
Packit |
857059 |
} ELEMENT_TABLE_ENTRY;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// Element table flags:
|
|
Packit |
857059 |
#define ELEM_NAMEPREPEND 0x80 // Data prepended to element name
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// list of elements which a given tag matched and the attribute value
|
|
Packit |
857059 |
// which the element selected. This is generated by the start tag handler
|
|
Packit |
857059 |
// and used by the end tag handler for a given "matched" tag
|
|
Packit |
857059 |
typedef struct
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
int ix; // element table index
|
|
Packit |
857059 |
int lenAttrValue; // length of value
|
|
Packit |
857059 |
char *pAttrValue; // value, NULL if not outputting attr
|
|
Packit |
857059 |
} ELEMENT_LIST_ENTRY;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
typedef struct
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
int numElements; // number of entrys in list
|
|
Packit |
857059 |
ELEMENT_LIST_ENTRY Elements[1]; // variable length list
|
|
Packit |
857059 |
} ELEMENT_LIST;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
|
|
Packit |
857059 |
/*******************************************************************************
|
|
Packit |
857059 |
*
|
|
Packit |
857059 |
* LOCAL FUNCTION PROTOTYPES
|
|
Packit |
857059 |
*/
|
|
Packit |
857059 |
|
|
Packit |
857059 |
int delWsLead(char *pStr);
|
|
Packit |
857059 |
int delWsTrail(char *pStr);
|
|
Packit |
857059 |
void dispExtractionRecord();
|
|
Packit |
857059 |
void dispHeaderRecord(int argc, char ** argv);
|
|
Packit |
857059 |
void errUsage(void);
|
|
Packit |
857059 |
int findElement(int start, const char *pElement, const char **pAttrib,
|
|
Packit |
857059 |
char **pValue, int *length);
|
|
Packit |
857059 |
int findElementDup(const ELEMENT_TABLE_ENTRY *pElement);
|
|
Packit |
857059 |
void getRecu_opt( int argc, char ** argv, const char *pOptShort,
|
|
Packit |
857059 |
struct option tbOptLong[] );
|
|
Packit |
857059 |
void *procElementBeg(IXmlParserState_t *pParserState, void *pParent, const char **ppAttrib);
|
|
Packit |
857059 |
void procElementEnd( IXmlParserState_t *pParserState, const IXML_FIELD *pField,
|
|
Packit |
857059 |
void *pObject, void *pParent, XML_Char *pContent, unsigned length,
|
|
Packit |
857059 |
boolean flValid );
|
|
Packit |
857059 |
|
|
Packit |
857059 |
|
|
Packit |
857059 |
/*******************************************************************************
|
|
Packit |
857059 |
*
|
|
Packit |
857059 |
* GLOBAL VARIABLES
|
|
Packit |
857059 |
*/
|
|
Packit |
857059 |
|
|
Packit |
857059 |
int g_exitstatus = 0;
|
|
Packit |
857059 |
int g_verbose = 0;
|
|
Packit |
857059 |
int g_quiet = 0;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
|
|
Packit |
857059 |
/*******************************************************************************
|
|
Packit |
857059 |
*
|
|
Packit |
857059 |
* LOCAL VARIABLES
|
|
Packit |
857059 |
*/
|
|
Packit |
857059 |
|
|
Packit |
857059 |
int levelParse = 0; // Parse nesting level
|
|
Packit |
857059 |
int numElementsTable = 0; // Number of elements in tbElements[]
|
|
Packit |
857059 |
int numElementsExtract = 0; // Number of elements to extract
|
|
Packit |
857059 |
int ctElementsSuppress = 0; // Count of suppress elements being parsed
|
|
Packit |
857059 |
int flElementChangeLast = FALSE; // tbElement[] value change flag (last line)
|
|
Packit |
857059 |
int flElementChange = FALSE; // tbElement[] value change flag
|
|
Packit |
857059 |
int flHeaderOutput = TRUE; // Header output flag
|
|
Packit |
857059 |
XML_Parser pParser = NULL; // Pointer to expat parser object
|
|
Packit |
857059 |
|
|
Packit |
857059 |
FILE * hFileInput = NULL; // Input file handle (default stdin)
|
|
Packit |
857059 |
// Input file name (default stdin)
|
|
Packit |
857059 |
char nameFileInput[MAX_FILENAME_CHARS + 1] = "stdin";
|
|
Packit |
857059 |
uint32 fvDebugProg = 0; // Debug/Trace variable as:
|
|
Packit |
857059 |
// 0MMM MMMM NNNN NNNN SSSS 21RC SIEB SNEB
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// Command line option table, each has a short and long flag name
|
|
Packit |
857059 |
static const char* tbShortOptions="#vHe:s:X:P:d:Z:";
|
|
Packit |
857059 |
struct option tbOptions[] =
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
// Basic controls
|
|
Packit |
857059 |
{ "help", no_argument, NULL, 'h' },
|
|
Packit |
857059 |
{ "verbose", no_argument, NULL, 'v' },
|
|
Packit |
857059 |
{ "extract", required_argument, NULL, 'e' },
|
|
Packit |
857059 |
{ "suppress", required_argument, NULL, 's' },
|
|
Packit |
857059 |
{ "infile", required_argument, NULL, 'X' },
|
|
Packit |
857059 |
{ "pfile", required_argument, NULL, 'P' },
|
|
Packit |
857059 |
{ "delimit", required_argument, NULL, 'd' },
|
|
Packit |
857059 |
{ "noheader", no_argument, NULL, 'H' },
|
|
Packit |
857059 |
{ "debug", required_argument, NULL, 'Z' },
|
|
Packit |
857059 |
{ 0 }
|
|
Packit |
857059 |
};
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// Element table; contains information about each element of interest.
|
|
Packit |
857059 |
// Elements to be extracted are contained at the beginning of the table
|
|
Packit |
857059 |
// (0 - numElementsExtract-1); elements for which extraction is suppressed
|
|
Packit |
857059 |
// are contained at the end of the table
|
|
Packit |
857059 |
// (numElementsExtract - numElementsTable-1).
|
|
Packit |
857059 |
ELEMENT_TABLE_ENTRY tbElements[MAX_ELEMENTS + 1];
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// IXML_FIELD table; contains information for the XML Lib parser. For
|
|
Packit |
857059 |
// purposes of opaxmlextract, a call-back on every start tag and end tag
|
|
Packit |
857059 |
// is required; therefore IXML_FIELD tag is set to "*" and format to 'w'.
|
|
Packit |
857059 |
IXML_FIELD tbFields[] =
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
{tag:"*", format:'w', subfields:tbFields, start_func:procElementBeg,
|
|
Packit |
857059 |
end_func:procElementEnd},
|
|
Packit |
857059 |
{NULL}
|
|
Packit |
857059 |
};
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// Delimiter string buffer
|
|
Packit |
857059 |
char bfDelimit[MAX_DELIMIT_CHARS + 1] = ";";
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// Input buffer
|
|
Packit |
857059 |
char bfInput[MAX_INPUT_BUF];
|
|
Packit |
857059 |
|
|
Packit |
857059 |
void *mymalloc(size_t size, const char* desc)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
void *ret = malloc(size);
|
|
Packit |
857059 |
if (! ret)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
fprintf(stderr, NAME_PROG ": Unable to Allocate %s Memory\n", desc);
|
|
Packit |
857059 |
exit(1);
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
return ret;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
void *myrealloc(void* ptr, size_t size, const char* desc)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
void *ret = realloc(ptr, size);
|
|
Packit |
857059 |
if (! ret)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
fprintf(stderr, NAME_PROG ": Unable to Re-Allocate %s Memory\n", desc);
|
|
Packit |
857059 |
exit(1);
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
return ret;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
/*******************************************************************************
|
|
Packit |
857059 |
*
|
|
Packit |
857059 |
* delWsLead()
|
|
Packit |
857059 |
*
|
|
Packit |
857059 |
* Description:
|
|
Packit |
857059 |
* Delete leading white space from a string. White space is defined by the
|
|
Packit |
857059 |
* string WHITE_SPACE.
|
|
Packit |
857059 |
*
|
|
Packit |
857059 |
* Inputs:
|
|
Packit |
857059 |
* pStr - Pointer to string from which to delete leading white space
|
|
Packit |
857059 |
*
|
|
Packit |
857059 |
* Outputs:
|
|
Packit |
857059 |
* ERROR - pStr NULL
|
|
Packit |
857059 |
* OK - white space deleted, no white space to delete
|
|
Packit |
857059 |
*/
|
|
Packit |
857059 |
int delWsLead(char *pStr)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
int nChar;
|
|
Packit |
857059 |
char *pChar;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
if (!pStr)
|
|
Packit |
857059 |
return (ERROR);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
nChar = strspn(pStr, WHITE_SPACE);
|
|
Packit |
857059 |
if (nChar != 0)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
pChar = pStr + nChar;
|
|
Packit |
857059 |
memmove(pStr, pChar, strlen(pChar) + 1);
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
return (OK);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
} // End of delWsLead()
|
|
Packit |
857059 |
|
|
Packit |
857059 |
|
|
Packit |
857059 |
/*******************************************************************************
|
|
Packit |
857059 |
*
|
|
Packit |
857059 |
* delWsTrail()
|
|
Packit |
857059 |
*
|
|
Packit |
857059 |
* Description:
|
|
Packit |
857059 |
* Delete trailing white space from a string. White space is defined by the
|
|
Packit |
857059 |
* string WHITE_SPACE.
|
|
Packit |
857059 |
*
|
|
Packit |
857059 |
* Inputs:
|
|
Packit |
857059 |
* pStr - Pointer to string from which to delete trailing white space
|
|
Packit |
857059 |
*
|
|
Packit |
857059 |
* Outputs:
|
|
Packit |
857059 |
* ERROR - pStr NULL
|
|
Packit |
857059 |
* OK - white space deleted, no white space to delete
|
|
Packit |
857059 |
*/
|
|
Packit |
857059 |
int delWsTrail(char *pStr)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
int nChar;
|
|
Packit |
857059 |
char *pChar;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
if (!(pChar = pStr))
|
|
Packit |
857059 |
return (ERROR); // pStr is NULL
|
|
Packit |
857059 |
|
|
Packit |
857059 |
while (TRUE)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
// Find next non-white space char
|
|
Packit |
857059 |
nChar = strspn(pChar, WHITE_SPACE);
|
|
Packit |
857059 |
if (pChar[nChar])
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
// Find next white space char
|
|
Packit |
857059 |
pChar += nChar;
|
|
Packit |
857059 |
pChar += strcspn(pChar, WHITE_SPACE);
|
|
Packit |
857059 |
if (!*pChar)
|
|
Packit |
857059 |
break; // No trailing white space
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// Found first white space char after last non-white space char
|
|
Packit |
857059 |
else
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
*pChar = 0;
|
|
Packit |
857059 |
break;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
} // End of while (TRUE)
|
|
Packit |
857059 |
|
|
Packit |
857059 |
return (OK);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
} // End of delWsTrail()
|
|
Packit |
857059 |
|
|
Packit |
857059 |
|
|
Packit |
857059 |
/*******************************************************************************
|
|
Packit |
857059 |
*
|
|
Packit |
857059 |
* dispExtractionRecord()
|
|
Packit |
857059 |
*
|
|
Packit |
857059 |
* Description:
|
|
Packit |
857059 |
* Display (output) 1 record of extraction data if element change flag
|
|
Packit |
857059 |
* indicates an element has changed since the last output.
|
|
Packit |
857059 |
*
|
|
Packit |
857059 |
* Inputs:
|
|
Packit |
857059 |
* none
|
|
Packit |
857059 |
*
|
|
Packit |
857059 |
* Outputs:
|
|
Packit |
857059 |
* none
|
|
Packit |
857059 |
*/
|
|
Packit |
857059 |
void dispExtractionRecord()
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
int ix; // Loop index
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// Check element change flag
|
|
Packit |
857059 |
if (!flElementChangeLast)
|
|
Packit |
857059 |
return;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// Output extraction record: element values
|
|
Packit |
857059 |
for (ix = 0; ix < numElementsExtract; ix++)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
(void)delWsTrail(tbElements[ix].pValue);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
if (ix > 0)
|
|
Packit |
857059 |
printf("%s", bfDelimit);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
printf("%s", tbElements[ix].pValue ? tbElements[ix].pValue : "" );
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
printf("\n");
|
|
Packit |
857059 |
flElementChangeLast = FALSE;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
} // End of dispExtractionRecord()
|
|
Packit |
857059 |
|
|
Packit |
857059 |
void printElement(FILE *f, ELEMENT_TABLE_ENTRY *pElement, int verbose)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
// Output complete name string if verbose or name not prepended
|
|
Packit |
857059 |
if (verbose || !(pElement->flags & ELEM_NAMEPREPEND))
|
|
Packit |
857059 |
fprintf(f, "%s", pElement->pName);
|
|
Packit |
857059 |
else
|
|
Packit |
857059 |
fprintf(f, "%s", &pElement->pName[2]);
|
|
Packit |
857059 |
if (pElement->pAttrName)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
fprintf(f, ":%s", pElement->pAttrName);
|
|
Packit |
857059 |
if (pElement->pAttrValue)
|
|
Packit |
857059 |
fprintf(f, ":%s", pElement->pAttrValue);
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
/*******************************************************************************
|
|
Packit |
857059 |
*
|
|
Packit |
857059 |
* dispHeaderRecord()
|
|
Packit |
857059 |
*
|
|
Packit |
857059 |
* Description:
|
|
Packit |
857059 |
* Display (output) header line containing names of elements extracted. This
|
|
Packit |
857059 |
* line preceeds the extraction data. If verbose is set, preceed the header
|
|
Packit |
857059 |
* line with a line containing the program name and command line options.
|
|
Packit |
857059 |
*
|
|
Packit |
857059 |
* Inputs:
|
|
Packit |
857059 |
* argc, argv - Inputs to main()
|
|
Packit |
857059 |
*
|
|
Packit |
857059 |
* Outputs:
|
|
Packit |
857059 |
* none
|
|
Packit |
857059 |
*/
|
|
Packit |
857059 |
void dispHeaderRecord(int argc, char ** argv)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
int ix; // Loop index
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// Output header record only if output enabled
|
|
Packit |
857059 |
if (flHeaderOutput)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
// Output element names as a header
|
|
Packit |
857059 |
for (ix = 0; ix < numElementsExtract; ix++)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
if (ix > 0)
|
|
Packit |
857059 |
printf("%s", bfDelimit);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
printElement(stdout,&tbElements[ix], g_verbose);
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
printf("\n");
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
} // End of dispHeaderRecord()
|
|
Packit |
857059 |
|
|
Packit |
857059 |
|
|
Packit |
857059 |
/*******************************************************************************
|
|
Packit |
857059 |
*
|
|
Packit |
857059 |
* errUsage()
|
|
Packit |
857059 |
*
|
|
Packit |
857059 |
* Description:
|
|
Packit |
857059 |
* Output information about program usage and parameters.
|
|
Packit |
857059 |
*
|
|
Packit |
857059 |
* Inputs:
|
|
Packit |
857059 |
* none
|
|
Packit |
857059 |
*
|
|
Packit |
857059 |
* Outputs:
|
|
Packit |
857059 |
* none
|
|
Packit |
857059 |
*/
|
|
Packit |
857059 |
void errUsage(void)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
fprintf(stderr, "Usage: " NAME_PROG " [-v][-H][-d delimiter][-e element][-s element]\n");
|
|
Packit |
857059 |
fprintf(stderr, " [-X input_file] [-P param_file]\n");
|
|
Packit |
857059 |
fprintf(stderr, " -e/--extract element - name of an XML element to extract\n");
|
|
Packit |
857059 |
fprintf(stderr, " can be used multiple times\n");
|
|
Packit |
857059 |
fprintf(stderr, " elements can be nested in any order, but will\n");
|
|
Packit |
857059 |
fprintf(stderr, " be output in the order specified\n");
|
|
Packit |
857059 |
fprintf(stderr, " optionally an attribute or\n");
|
|
Packit |
857059 |
fprintf(stderr, " attribute and value can be specified\n");
|
|
Packit |
857059 |
fprintf(stderr, " -e element\n");
|
|
Packit |
857059 |
fprintf(stderr, " -e element:attrName\n");
|
|
Packit |
857059 |
fprintf(stderr, " -e element:attrName:attrValue\n\n");
|
|
Packit |
857059 |
fprintf(stderr, " Note that elements can be compound values\n");
|
|
Packit |
857059 |
fprintf(stderr, " separated by a dot. For example,\n");
|
|
Packit |
857059 |
fprintf(stderr, " 'Switches.Node' is a Node element contained\n");
|
|
Packit |
857059 |
fprintf(stderr, " within a Switches element.\n\n");
|
|
Packit |
857059 |
fprintf(stderr, " If its desired to output the attribute value as\n");
|
|
Packit |
857059 |
fprintf(stderr, " opposed to the element value, a specification such\n");
|
|
Packit |
857059 |
fprintf(stderr, " as '-e FIs.Node:id' can be used, which will return\n");
|
|
Packit |
857059 |
fprintf(stderr, " the value of the id attribute of any Node elements\n");
|
|
Packit |
857059 |
fprintf(stderr, " within FIs element. If desired a specific element\n");
|
|
Packit |
857059 |
fprintf(stderr, " can be selected by its attribute value, such as\n");
|
|
Packit |
857059 |
fprintf(stderr, " '-e MulticastFDB.Value:LID:0xc000', which will\n");
|
|
Packit |
857059 |
fprintf(stderr, " return the value of the Value element within\n");
|
|
Packit |
857059 |
fprintf(stderr, " Multicast FDB element where the Value element has\n");
|
|
Packit |
857059 |
fprintf(stderr, " an attribute of LID with a value of 0xc000.\n\n");
|
|
Packit |
857059 |
|
|
Packit |
857059 |
#if ALLOW_MULTI_MATCH
|
|
Packit |
857059 |
fprintf(stderr, " A given element can be specified multiple\n");
|
|
Packit |
857059 |
fprintf(stderr, " times each with a different AttrName or attrValue\n");
|
|
Packit |
857059 |
#else
|
|
Packit |
857059 |
fprintf(stderr, " a given element can be specified only once\n");
|
|
Packit |
857059 |
#endif
|
|
Packit |
857059 |
fprintf(stderr, " -s/--suppress element - name of XML element to suppress extraction\n");
|
|
Packit |
857059 |
fprintf(stderr, " can be used multiple times, order does not matter\n");
|
|
Packit |
857059 |
fprintf(stderr, " supports same syntaxes as -e\n");
|
|
Packit |
857059 |
fprintf(stderr, " -d/--delimit delimiter - delimiter output between element names and values\n");
|
|
Packit |
857059 |
fprintf(stderr, " default is semicolon\n");
|
|
Packit |
857059 |
fprintf(stderr, " -X/--infile input_file - parse XML in input_file\n");
|
|
Packit |
857059 |
fprintf(stderr, " -P/--pfile param_file - read command parameters from param_file\n");
|
|
Packit |
857059 |
fprintf(stderr, " -H/--noheader - do not output element name header record\n");
|
|
Packit |
857059 |
fprintf(stderr, " -v/--verbose - verbose output: progress reports during extraction\n");
|
|
Packit |
857059 |
fprintf(stderr, " and element name prepended wildcard characters\n");
|
|
Packit |
857059 |
fprintf(stderr, " --help - print this usage text.\n");
|
|
Packit |
857059 |
|
|
Packit |
857059 |
if (hFileInput && (hFileInput != stdin))
|
|
Packit |
857059 |
fclose(hFileInput);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
exit(2);
|
|
Packit |
857059 |
} // End of errUsage()
|
|
Packit |
857059 |
|
|
Packit |
857059 |
|
|
Packit |
857059 |
/*******************************************************************************
|
|
Packit |
857059 |
*
|
|
Packit |
857059 |
* findElement()
|
|
Packit |
857059 |
*
|
|
Packit |
857059 |
* Description:
|
|
Packit |
857059 |
* Find specified element name in element table using wildcard matching.
|
|
Packit |
857059 |
* Search suppression elements first by starting search at end of table
|
|
Packit |
857059 |
* and searching toward beginning.
|
|
Packit |
857059 |
*
|
|
Packit |
857059 |
* Inputs:
|
|
Packit |
857059 |
* start - first element in table to check (end of table)
|
|
Packit |
857059 |
* pElement - Pointer to element name
|
|
Packit |
857059 |
* ppAttrib - attribute list from tag being processed
|
|
Packit |
857059 |
*
|
|
Packit |
857059 |
* Outputs:
|
|
Packit |
857059 |
* Index of element table containing element name, else
|
|
Packit |
857059 |
* ERROR - Element name not found
|
|
Packit |
857059 |
*
|
|
Packit |
857059 |
* *pValue, *length - if matched a Name:attrName style specifier, the value of
|
|
Packit |
857059 |
* the attribute matched. Otherwise NULL,0
|
|
Packit |
857059 |
* (caller must free *pValue if non-NULL)
|
|
Packit |
857059 |
*/
|
|
Packit |
857059 |
int findElement(int start, const char *pElement, const char **ppAttrib,
|
|
Packit |
857059 |
char **pValue, int *length)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
int ix;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
*pValue = NULL;
|
|
Packit |
857059 |
*length = 0;
|
|
Packit |
857059 |
for (ix = start; ix >= 0; ix--)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
ELEMENT_TABLE_ENTRY *p = &tbElements[ix];
|
|
Packit |
857059 |
if (!fnmatch(p->pName, pElement, 0))
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
int i;
|
|
Packit |
857059 |
if (! p->pAttrName)
|
|
Packit |
857059 |
return (ix); // match only on tag name
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// search for matching attribute
|
|
Packit |
857059 |
// even index in ppAttrib is name, odd is corresponding value
|
|
Packit |
857059 |
for (i=0; ppAttrib[i]; i += 2)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
if (!fnmatch(p->pAttrName, ppAttrib[i], 0))
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
if (! p->pAttrValue)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
// match on Attr Name and return attr value
|
|
Packit |
857059 |
*length = strlen(ppAttrib[i+1]);
|
|
Packit |
857059 |
*pValue = mymalloc(*length+1, "Attribute Value");
|
|
Packit |
857059 |
strcpy(*pValue, ppAttrib[i+1]);
|
|
Packit |
857059 |
return (ix);
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
// match on attr value
|
|
Packit |
857059 |
if (! fnmatch(p->pAttrValue, ppAttrib[i+1], 0))
|
|
Packit |
857059 |
return (ix);
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
return (ERROR);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
} // End of findElement()
|
|
Packit |
857059 |
|
|
Packit |
857059 |
|
|
Packit |
857059 |
/*******************************************************************************
|
|
Packit |
857059 |
*
|
|
Packit |
857059 |
* findElementDup()
|
|
Packit |
857059 |
*
|
|
Packit |
857059 |
* Description:
|
|
Packit |
857059 |
* Find specified element name in element table using duplicate (2-way)
|
|
Packit |
857059 |
* wildcard matching. Search element table from beginning to end since
|
|
Packit |
857059 |
* there is no need to check suppression elements first.
|
|
Packit |
857059 |
*
|
|
Packit |
857059 |
* Inputs:
|
|
Packit |
857059 |
* pElement - Pointer to element name
|
|
Packit |
857059 |
*
|
|
Packit |
857059 |
* Outputs:
|
|
Packit |
857059 |
* Index of element table containing element name, else
|
|
Packit |
857059 |
* ERROR - Element name not found
|
|
Packit |
857059 |
*/
|
|
Packit |
857059 |
int findElementDup(const ELEMENT_TABLE_ENTRY *pElement)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
int ix;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
for (ix = 0; ix < numElementsTable; ix++)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
ELEMENT_TABLE_ENTRY *p = &tbElements[ix];
|
|
Packit |
857059 |
if (0 == fnmatch(p->pName, pElement->pName, 0)
|
|
Packit |
857059 |
|| 0 == fnmatch(pElement->pName, p->pName, 0))
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
#if ALLOW_MULTI_MATCH
|
|
Packit |
857059 |
if ((p->pAttrName == NULL) != (pElement->pAttrName == NULL))
|
|
Packit |
857059 |
continue;
|
|
Packit |
857059 |
if (p->pAttrName && pElement->pAttrName)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
if ( 0 == fnmatch(p->pAttrName, pElement->pAttrName, 0) ||
|
|
Packit |
857059 |
0 == fnmatch(pElement->pAttrName, p->pAttrName, 0) )
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
if ((p->pAttrValue == NULL) != (pElement->pAttrValue == NULL))
|
|
Packit |
857059 |
continue;
|
|
Packit |
857059 |
if ( p->pAttrValue && pElement->pAttrValue &&
|
|
Packit |
857059 |
! ( 0 == fnmatch(p->pAttrValue, pElement->pAttrValue, 0) ||
|
|
Packit |
857059 |
0 == fnmatch(pElement->pAttrValue, p->pAttrValue, 0) ) )
|
|
Packit |
857059 |
continue;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
return (ix);
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
continue;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
#else
|
|
Packit |
857059 |
// allow different values for same attr because won't both match
|
|
Packit |
857059 |
// the same tag
|
|
Packit |
857059 |
if (p->pAttrName && pElement->pAttrName
|
|
Packit |
857059 |
&& (0 == fnmatch(p->pAttrName, pElement->pAttrName, 0)
|
|
Packit |
857059 |
|| 0 == fnmatch(pElement->pAttrName, p->pAttrName, 0))
|
|
Packit |
857059 |
&& p->pAttrValue && pElement->pAttrValue
|
|
Packit |
857059 |
&& ! (0 == fnmatch(p->pAttrValue, pElement->pAttrValue, 0)
|
|
Packit |
857059 |
|| 0 == fnmatch(pElement->pAttrValue, p->pAttrValue, 0)))
|
|
Packit |
857059 |
continue;
|
|
Packit |
857059 |
#endif
|
|
Packit |
857059 |
return (ix);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
} // End of if (0 == fnmatch(p->pName, pElement->pName, 0)
|
|
Packit |
857059 |
|
|
Packit |
857059 |
} // End of for (ix = 0; ix < numElementsTable; ix++)
|
|
Packit |
857059 |
|
|
Packit |
857059 |
return (ERROR);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
} // End of findElementDup()
|
|
Packit |
857059 |
|
|
Packit |
857059 |
void getNextField(const char *arg, int extra, char **field, const char **rest)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
const char *p = rest?strchr(arg, ':'):NULL;
|
|
Packit |
857059 |
int len;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
if (p)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
len = (p-arg);
|
|
Packit |
857059 |
*rest = p+1;
|
|
Packit |
857059 |
} else {
|
|
Packit |
857059 |
len = strlen(arg);
|
|
Packit |
857059 |
if (rest)
|
|
Packit |
857059 |
*rest = NULL;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
*field = mymalloc(len+1+extra, "Name");
|
|
Packit |
857059 |
strncpy(*field, arg, len);
|
|
Packit |
857059 |
(*field)[len] = '\0';
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
|
|
Packit |
857059 |
/*******************************************************************************
|
|
Packit |
857059 |
*
|
|
Packit |
857059 |
* getRecu_opt()
|
|
Packit |
857059 |
*
|
|
Packit |
857059 |
* Description:
|
|
Packit |
857059 |
* Get command line options (recursively). Parses command line options
|
|
Packit |
857059 |
* using short and long option (parameter) definitions. Parameters (global
|
|
Packit |
857059 |
* variables) are updated appropriately. The parameter '-P param_file' which
|
|
Packit |
857059 |
* takes command line options from a file is also handled. The -P parameter
|
|
Packit |
857059 |
* can be used within a parameter file; in such cases the function will call
|
|
Packit |
857059 |
* itself recursively.
|
|
Packit |
857059 |
*
|
|
Packit |
857059 |
* Inputs:
|
|
Packit |
857059 |
* argc - Number of input parameters
|
|
Packit |
857059 |
* argv - Array of pointers to input parameters
|
|
Packit |
857059 |
* pOptShort - Pointer to string of short option definitions
|
|
Packit |
857059 |
* tbOptLong - Array of long option definitions
|
|
Packit |
857059 |
*
|
|
Packit |
857059 |
* Outputs:
|
|
Packit |
857059 |
* none
|
|
Packit |
857059 |
*/
|
|
Packit |
857059 |
void getRecu_opt( int argc, char ** argv, const char *pOptShort,
|
|
Packit |
857059 |
struct option tbOptLong[] )
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
int ix;
|
|
Packit |
857059 |
int cOpt; // Option parsing char
|
|
Packit |
857059 |
int ixOpt; // Option parsing index
|
|
Packit |
857059 |
int lenStr; // String length
|
|
Packit |
857059 |
char *pChar; // Pointer to char
|
|
Packit |
857059 |
ELEMENT_TABLE_ENTRY *pElement1, // Pointers to element entries
|
|
Packit |
857059 |
*pElement2;
|
|
Packit |
857059 |
int argc_recu; // Recursive argc
|
|
Packit |
857059 |
char *argv_recu[MAX_PARAMS_FILE]; // Recursive argv
|
|
Packit |
857059 |
int optind_recu; // Recursive optind
|
|
Packit |
857059 |
char *optarg_recu; // Recursive optarg
|
|
Packit |
857059 |
|
|
Packit |
857059 |
int ctCharParam; // Parameter file char count
|
|
Packit |
857059 |
FILE *hFileParam = NULL; // Parameter file handle
|
|
Packit |
857059 |
char nameFileParam[MAX_FILENAME_CHARS +1]; // Parameter file name
|
|
Packit |
857059 |
char bfParam[MAX_PARAM_BUF + 1];
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// Input command line arguments
|
|
Packit |
857059 |
while ((cOpt = getopt_long(argc, argv, pOptShort, tbOptLong, &ixOpt)) != -1)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
lenStr = 0;
|
|
Packit |
857059 |
switch (cOpt)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
// Verbose
|
|
Packit |
857059 |
case 'v':
|
|
Packit |
857059 |
g_verbose = 1;
|
|
Packit |
857059 |
break;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// Extract element name specification
|
|
Packit |
857059 |
case 'e':
|
|
Packit |
857059 |
// Suppress element name specification
|
|
Packit |
857059 |
case 's':
|
|
Packit |
857059 |
// syntaxes supported:
|
|
Packit |
857059 |
// Name - match Tag with given name
|
|
Packit |
857059 |
// Name:attr - select attr field of Tag with given name and attr
|
|
Packit |
857059 |
// Name:attr:value - match Tag with given name and attr value
|
|
Packit |
857059 |
// All three components allow "glob" style patterns
|
|
Packit |
857059 |
if (numElementsTable == MAX_ELEMENTS)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
fprintf(stderr, NAME_PROG ": Too many Elements\n");
|
|
Packit |
857059 |
errUsage();
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
else if (!optarg || ! *optarg)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
fprintf(stderr, NAME_PROG ": Missing Element\n");
|
|
Packit |
857059 |
errUsage();
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
else
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
ELEMENT_TABLE_ENTRY *pElement = &tbElements[numElementsTable];
|
|
Packit |
857059 |
const char *rest;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// Tag Name
|
|
Packit |
857059 |
getNextField(optarg, 2, &pElement->pName, &rest);
|
|
Packit |
857059 |
if (! strchr(optarg, '*'))
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
// insert *. before string (extra 2 above allowed space)
|
|
Packit |
857059 |
memmove(pElement->pName+2, pElement->pName, strlen(pElement->pName)+1);
|
|
Packit |
857059 |
pElement->pName[0] = '*'; pElement->pName[1] = '.';
|
|
Packit |
857059 |
pElement->flags |= ELEM_NAMEPREPEND;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
if (rest) {
|
|
Packit |
857059 |
// optional AttrName
|
|
Packit |
857059 |
if (! *rest) // trailing colon
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
fprintf(stderr, NAME_PROG ": Attr Name missing: %s\n", optarg);
|
|
Packit |
857059 |
errUsage();
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
getNextField(rest, 0, &pElement->pAttrName, &rest);
|
|
Packit |
857059 |
if (rest) {
|
|
Packit |
857059 |
// optional AttrValue
|
|
Packit |
857059 |
if (! *rest) // trailing colon
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
fprintf(stderr, NAME_PROG ": Attr Value missing: %s\n", optarg);
|
|
Packit |
857059 |
errUsage();
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
getNextField(rest, 0, &pElement->pAttrValue, NULL);
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
if ((ix = findElementDup(&tbElements[numElementsTable])) != ERROR)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
fprintf(stderr, NAME_PROG ": Duplicate (matching) Element: %s (matches: ", optarg);
|
|
Packit |
857059 |
printElement(stderr, &tbElements[ix], FALSE);
|
|
Packit |
857059 |
fprintf(stderr, ")\n");
|
|
Packit |
857059 |
errUsage();
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// If suppress specification, leave at end of tbElements[]
|
|
Packit |
857059 |
if (cOpt == 's')
|
|
Packit |
857059 |
numElementsTable++;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// If extraction specification w/no suppress elements, leave at
|
|
Packit |
857059 |
// end of tbElements[]
|
|
Packit |
857059 |
else if ((cOpt == 'e') && (numElementsExtract == numElementsTable))
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
numElementsTable++;
|
|
Packit |
857059 |
numElementsExtract++;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// If extraction specification w/suppress elements, move extraction
|
|
Packit |
857059 |
// to end of other extractions
|
|
Packit |
857059 |
else if ((cOpt == 'e') && (numElementsExtract < numElementsTable))
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
// Swap last element table entry with first suppress element entry
|
|
Packit |
857059 |
// (NOTE: lenValue, pValue and level are zero, so no swap needed)
|
|
Packit |
857059 |
pElement1 = &tbElements[numElementsExtract++];
|
|
Packit |
857059 |
pElement2 = &tbElements[numElementsTable++];
|
|
Packit |
857059 |
|
|
Packit |
857059 |
pChar = pElement1->pName;
|
|
Packit |
857059 |
pElement1->pName = pElement2->pName;
|
|
Packit |
857059 |
pElement2->pName = pChar;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
pChar = pElement1->pAttrName;
|
|
Packit |
857059 |
pElement1->pAttrName = pElement2->pAttrName;
|
|
Packit |
857059 |
pElement2->pAttrName = pChar;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
pChar = pElement1->pAttrValue;
|
|
Packit |
857059 |
pElement1->pAttrValue = pElement2->pAttrValue;
|
|
Packit |
857059 |
pElement2->pAttrValue = pChar;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
lenStr = pElement1->flags;
|
|
Packit |
857059 |
pElement1->flags = pElement2->flags;
|
|
Packit |
857059 |
pElement2->flags = lenStr;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
break;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// Delimiter string specification
|
|
Packit |
857059 |
case 'd':
|
|
Packit |
857059 |
if ( !optarg || ((lenStr = strlen(optarg)) == 0) ||
|
|
Packit |
857059 |
(lenStr > MAX_DELIMIT_CHARS) )
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
fprintf(stderr, NAME_PROG ": Invalid delimiter size: %d\n", lenStr);
|
|
Packit |
857059 |
errUsage();
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
strncpy(bfDelimit, optarg, sizeof(bfDelimit)-1);
|
|
Packit |
857059 |
// Ensure null termination
|
|
Packit |
857059 |
bfDelimit[MAX_DELIMIT_CHARS]=0;
|
|
Packit |
857059 |
break;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// Input file specification
|
|
Packit |
857059 |
case 'X':
|
|
Packit |
857059 |
if ( !optarg || ((lenStr = strlen(optarg)) == 0) ||
|
|
Packit |
857059 |
(lenStr > MAX_FILENAME_CHARS) )
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
fprintf(stderr, NAME_PROG ": Missing Input File Name.\n");
|
|
Packit |
857059 |
errUsage();
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
else if (hFileInput != stdin)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
fprintf( stderr, NAME_PROG ": Multiple Input Files: %s and %s\n",
|
|
Packit |
857059 |
nameFileInput, optarg );
|
|
Packit |
857059 |
errUsage();
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
strncpy(nameFileInput, optarg, sizeof(nameFileInput)-1);
|
|
Packit |
857059 |
// Ensure null termination
|
|
Packit |
857059 |
nameFileInput[MAX_FILENAME_CHARS]=0;
|
|
Packit |
857059 |
hFileInput = fopen(nameFileInput, "r");
|
|
Packit |
857059 |
|
|
Packit |
857059 |
if (!hFileInput)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
fprintf( stderr, NAME_PROG ": Unable to Open Input File: %s\n",
|
|
Packit |
857059 |
nameFileInput );
|
|
Packit |
857059 |
perror("");
|
|
Packit |
857059 |
errUsage();
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
break;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// Parameter file specification
|
|
Packit |
857059 |
case 'P':
|
|
Packit |
857059 |
if (!optarg || ((lenStr = strlen(optarg)) == 0) ||
|
|
Packit |
857059 |
(lenStr > MAX_FILENAME_CHARS) )
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
fprintf(stderr, NAME_PROG ": Missing Parameter File Name.\n");
|
|
Packit |
857059 |
errUsage();
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// Open parameter file
|
|
Packit |
857059 |
strncpy(nameFileParam, optarg, sizeof(nameFileParam)-1);
|
|
Packit |
857059 |
// Ensure null termination
|
|
Packit |
857059 |
nameFileParam[MAX_FILENAME_CHARS]=0;
|
|
Packit |
857059 |
hFileParam = fopen(nameFileParam, "r");
|
|
Packit |
857059 |
|
|
Packit |
857059 |
if (!hFileParam)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
fprintf( stderr, NAME_PROG ": Unable to Open Parameter File: %s\n",
|
|
Packit |
857059 |
nameFileParam );
|
|
Packit |
857059 |
perror("");
|
|
Packit |
857059 |
errUsage();
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// Read parameter file
|
|
Packit |
857059 |
if (g_verbose)
|
|
Packit |
857059 |
fprintf(stderr, NAME_PROG ": Reading Param File: %s\n", nameFileParam);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
ctCharParam = (int)fread(bfParam, 1, MAX_PARAM_BUF, hFileParam);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
if (ferror(hFileParam))
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
fclose(hFileParam);
|
|
Packit |
857059 |
fprintf(stderr, NAME_PROG ": Read Error: %s\n", nameFileParam);
|
|
Packit |
857059 |
errUsage();
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
if ((ctCharParam == MAX_PARAM_BUF) && !feof(hFileParam))
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
fclose(hFileParam);
|
|
Packit |
857059 |
fprintf( stderr, NAME_PROG ": Parameter file (%s) too large (> %d bytes)\n",
|
|
Packit |
857059 |
nameFileParam, MAX_PARAM_BUF );
|
|
Packit |
857059 |
errUsage();
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// Make sure the buffer is null terminated.
|
|
Packit |
857059 |
bfParam[MAX_PARAM_BUF] = 0;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
fclose(hFileParam);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
if (ctCharParam > 0)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
// Parse parameter file into tokens
|
|
Packit |
857059 |
argc_recu = 2;
|
|
Packit |
857059 |
argv_recu[0] = nameFileParam;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
for (ix = 1; ; ix++, argc_recu++)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
if (ix == MAX_PARAMS_FILE)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
fprintf( stderr, NAME_PROG ": Parameter file (%s) has too many parameters (> %d)\n",
|
|
Packit |
857059 |
nameFileParam, MAX_PARAMS_FILE );
|
|
Packit |
857059 |
errUsage();
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
if ( (argv_recu[ix] = strtok((ix == 1) ? bfParam : NULL, WHITE_SPACE))
|
|
Packit |
857059 |
== NULL )
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
argc_recu--;
|
|
Packit |
857059 |
break;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
if (!strncmp(argv_recu[ix], "-P", OPTION_LEN))
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
fprintf( stderr, NAME_PROG ": Parameter file (%s) cannot contain -P option\n", nameFileParam);
|
|
Packit |
857059 |
errUsage();
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
if ( (argv_recu[ix] - bfParam + strlen(argv_recu[ix]) + 1) ==
|
|
Packit |
857059 |
ctCharParam )
|
|
Packit |
857059 |
break;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// Process parameter file parameters
|
|
Packit |
857059 |
if (argc_recu > 1)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
optind_recu = optind; // Save optind & optarg
|
|
Packit |
857059 |
optarg_recu = optarg;
|
|
Packit |
857059 |
optind = 1; // Init optind & optarg
|
|
Packit |
857059 |
optarg = NULL;
|
|
Packit |
857059 |
getRecu_opt(argc_recu, argv_recu, pOptShort, tbOptLong);
|
|
Packit |
857059 |
optind = optind_recu; // Restore optind & optarg
|
|
Packit |
857059 |
optarg = optarg_recu;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
} // End of if (ctCharParam > 0)
|
|
Packit |
857059 |
|
|
Packit |
857059 |
break;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// No Header
|
|
Packit |
857059 |
case 'H':
|
|
Packit |
857059 |
flHeaderOutput = FALSE;
|
|
Packit |
857059 |
break;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// Debug trace specification
|
|
Packit |
857059 |
case 'Z':
|
|
Packit |
857059 |
if (FSUCCESS != StringToUint32(&fvDebugProg, optarg, NULL, 0, TRUE)) {
|
|
Packit |
857059 |
fprintf(stderr, NAME_PROG ": Invalid Debug Setting: %s\n", optarg);
|
|
Packit |
857059 |
errUsage();
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
break;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
case '#':
|
|
Packit |
857059 |
default:
|
|
Packit |
857059 |
errUsage();
|
|
Packit |
857059 |
break;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
} // End of switch (cOpt)
|
|
Packit |
857059 |
|
|
Packit |
857059 |
} // End of while ( ( cOpt = getopt_long( argc, argv,
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// Validate command line arguments
|
|
Packit |
857059 |
if (optind < argc)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
fprintf(stderr, "%s: invalid argument %s\n", NAME_PROG, argv[optind]);
|
|
Packit |
857059 |
errUsage();
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
} // End of getRecu_opt()
|
|
Packit |
857059 |
|
|
Packit |
857059 |
|
|
Packit |
857059 |
/*******************************************************************************
|
|
Packit |
857059 |
*
|
|
Packit |
857059 |
* main()
|
|
Packit |
857059 |
*
|
|
Packit |
857059 |
* Description:
|
|
Packit |
857059 |
* main function for program.
|
|
Packit |
857059 |
*
|
|
Packit |
857059 |
* Inputs:
|
|
Packit |
857059 |
* argc - Number of input parameters
|
|
Packit |
857059 |
* argv - Array of pointers to input parameters
|
|
Packit |
857059 |
*
|
|
Packit |
857059 |
* Outputs:
|
|
Packit |
857059 |
* Exit status 0 - no errors
|
|
Packit |
857059 |
* Exit status 2 - error (input parameter, resources, file I/O, XML parsing)
|
|
Packit |
857059 |
*/
|
|
Packit |
857059 |
int main(int argc, char ** argv)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
int ix; // Loop index
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// Initialize for extraction
|
|
Packit |
857059 |
hFileInput = stdin;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
for (ix = 0; ix < MAX_ELEMENTS; ix++)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
tbElements[ix].pName = NULL;
|
|
Packit |
857059 |
tbElements[ix].pAttrName = NULL;
|
|
Packit |
857059 |
tbElements[ix].pAttrValue = NULL;
|
|
Packit |
857059 |
tbElements[ix].lenValue = 0;
|
|
Packit |
857059 |
tbElements[ix].pValue = NULL;
|
|
Packit |
857059 |
tbElements[ix].flags = 0;
|
|
Packit |
857059 |
tbElements[ix].level = 0;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// Get and validate command line arguments
|
|
Packit |
857059 |
getRecu_opt(argc, argv, tbShortOptions, tbOptions);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
dispHeaderRecord(argc, argv);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// Output progress report if g_verbose
|
|
Packit |
857059 |
if (g_verbose)
|
|
Packit |
857059 |
fprintf(stderr, NAME_PROG ": Parsing XML buffer\n");
|
|
Packit |
857059 |
|
|
Packit |
857059 |
if ( IXmlParseFile(hFileInput, nameFileInput, IXML_PARSER_FLAG_NONE, tbFields, NULL, NULL, NULL, NULL, NULL, NULL) !=
|
|
Packit |
857059 |
FSUCCESS )
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
fprintf(stderr, NAME_PROG ": XML Parse error\n");
|
|
Packit |
857059 |
exit(1);
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
if (hFileInput && (hFileInput != stdin))
|
|
Packit |
857059 |
fclose(hFileInput);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
return (g_exitstatus);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
} // End of main()
|
|
Packit |
857059 |
|
|
Packit |
857059 |
void ProcessMatchedElement( ELEMENT_TABLE_ENTRY *pElement, char *pValue,
|
|
Packit |
857059 |
int length, int level )
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
if (!length)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
// Existing element value being replaced by NULL
|
|
Packit |
857059 |
if (pElement->lenValue > 0)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
dispExtractionRecord();
|
|
Packit |
857059 |
pElement->pValue[0] = 0;
|
|
Packit |
857059 |
pElement->level = level;
|
|
Packit |
857059 |
flElementChange = TRUE;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
else
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
// Null element value being replaced by new value
|
|
Packit |
857059 |
if (!pElement->lenValue)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
// Allocate block of memory x2
|
|
Packit |
857059 |
pElement->pValue = mymalloc(length + length, "Value");
|
|
Packit |
857059 |
strcpy(pElement->pValue, pValue);
|
|
Packit |
857059 |
pElement->lenValue = length + length;
|
|
Packit |
857059 |
pElement->level = level;
|
|
Packit |
857059 |
flElementChange = TRUE;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
else if (pElement->lenValue < 0)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
if (-pElement->lenValue <= length)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
// Reallocate to larger block of memory x2
|
|
Packit |
857059 |
pElement->pValue =
|
|
Packit |
857059 |
myrealloc(pElement->pValue, length + length, "Value");
|
|
Packit |
857059 |
pElement->lenValue = -(length + length);
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
strcpy(pElement->pValue, pValue);
|
|
Packit |
857059 |
pElement->lenValue = -pElement->lenValue;
|
|
Packit |
857059 |
pElement->level = level;
|
|
Packit |
857059 |
flElementChange = TRUE;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
else
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
// Existing element value being replaced by new (non-equal) value
|
|
Packit |
857059 |
if (strcmp(pElement->pValue, pValue))
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
dispExtractionRecord();
|
|
Packit |
857059 |
if (pElement->lenValue <= length)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
// Reallocate to larger block of memory x2
|
|
Packit |
857059 |
pElement->pValue =
|
|
Packit |
857059 |
myrealloc(pElement->pValue, length + length, "Value");
|
|
Packit |
857059 |
pElement->lenValue = length + length;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
strcpy(pElement->pValue, pValue);
|
|
Packit |
857059 |
pElement->level = level;
|
|
Packit |
857059 |
flElementChange = TRUE;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
} // End of if (strcmp(pElement->pValue, pValue))
|
|
Packit |
857059 |
|
|
Packit |
857059 |
} // End of else (else if (pElement->lenValue < 0))
|
|
Packit |
857059 |
|
|
Packit |
857059 |
} // End of else (!length)
|
|
Packit |
857059 |
|
|
Packit |
857059 |
} // End of ProcessMatchedElement()
|
|
Packit |
857059 |
|
|
Packit |
857059 |
/*******************************************************************************
|
|
Packit |
857059 |
*
|
|
Packit |
857059 |
* procElementBeg()
|
|
Packit |
857059 |
*
|
|
Packit |
857059 |
* Description:
|
|
Packit |
857059 |
* Process begin element specification. Check for whether element suppresses
|
|
Packit |
857059 |
* extraction.
|
|
Packit |
857059 |
*
|
|
Packit |
857059 |
* Inputs:
|
|
Packit |
857059 |
* pParserState - Pointer to IXml parser state
|
|
Packit |
857059 |
* pParent - Pointer to element parent
|
|
Packit |
857059 |
* ppAttrib - Pointer to pointer to element attribute data
|
|
Packit |
857059 |
*
|
|
Packit |
857059 |
* Outputs:
|
|
Packit |
857059 |
* none
|
|
Packit |
857059 |
*/
|
|
Packit |
857059 |
void *procElementBeg(IXmlParserState_t *pParserState, void *pParent, const char **ppAttrib)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
int ix;
|
|
Packit |
857059 |
char *pNameFull;
|
|
Packit |
857059 |
ELEMENT_LIST* pList = NULL;
|
|
Packit |
857059 |
char *pValue;
|
|
Packit |
857059 |
int length;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
if (levelParse++ > MAX_LEVEL_PARSE)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
fprintf( stderr, NAME_PROG ": Max Parsing Level (%d) Exceeded\n",
|
|
Packit |
857059 |
MAX_LEVEL_PARSE );
|
|
Packit |
857059 |
exit(1);
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
pNameFull = (char *)IXmlParserGetCurrentFullTag(pParserState);
|
|
Packit |
857059 |
ix = numElementsTable - 1;
|
|
Packit |
857059 |
do {
|
|
Packit |
857059 |
if ((ix = findElement(ix, pNameFull, ppAttrib, &pValue, &length)) >= 0)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
#if ! SUPPRESS_AND_EXTRACT
|
|
Packit |
857059 |
if (pList && ix >= numElementsExtract) // Check for suppression Element
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
int i;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// discard matched extractions; replace with this suppression (below)
|
|
Packit |
857059 |
for (i=0; i<pList->numElements; i++)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
if (pList->Elements[i].pAttrValue)
|
|
Packit |
857059 |
free(pList->Elements[i].pAttrValue);
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
free(pList);
|
|
Packit |
857059 |
pList=NULL;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
#endif
|
|
Packit |
857059 |
// Process extraction of attribute value immediately so that value
|
|
Packit |
857059 |
// is available with (potential) extraction values of nested lines
|
|
Packit |
857059 |
if (pValue && ix < numElementsExtract)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
dispExtractionRecord();
|
|
Packit |
857059 |
ProcessMatchedElement( &tbElements[ix], pValue, length,
|
|
Packit |
857059 |
levelParse + 1 );
|
|
Packit |
857059 |
free(pValue);
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// Add to pList: extraction of element value
|
|
Packit |
857059 |
// extraction of element:attribute:value
|
|
Packit |
857059 |
// any suppression specification
|
|
Packit |
857059 |
else
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
if (pList)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
// sizeof(*pList) includes 1st element
|
|
Packit |
857059 |
pList = myrealloc(pList, sizeof(*pList)
|
|
Packit |
857059 |
+ pList->numElements
|
|
Packit |
857059 |
* sizeof(pList->Elements[0]),
|
|
Packit |
857059 |
"object list");
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
else
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
pList = mymalloc(sizeof(*pList), "object list");
|
|
Packit |
857059 |
pList->numElements = 0;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
// findElement has malloced pValue as needed
|
|
Packit |
857059 |
pList->Elements[pList->numElements].ix = ix;
|
|
Packit |
857059 |
pList->Elements[pList->numElements].lenAttrValue = length;
|
|
Packit |
857059 |
pList->Elements[pList->numElements].pAttrValue = pValue;
|
|
Packit |
857059 |
pList->numElements++;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// Check for suppression Element
|
|
Packit |
857059 |
if (ix >= numElementsExtract)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
ctElementsSuppress++;
|
|
Packit |
857059 |
break; // no use going past 1st match of a suppressed
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
ix--;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
} // End of if ((ix = findElement(ix, pNameFull, ppAttrib
|
|
Packit |
857059 |
|
|
Packit |
857059 |
#if ALLOW_MULTI_MATCH
|
|
Packit |
857059 |
} while (ix >= 0);
|
|
Packit |
857059 |
#else /* just use 1st match, like the old code did */
|
|
Packit |
857059 |
} while (0);
|
|
Packit |
857059 |
#endif
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// return list of elements matched (NULL if none matched)
|
|
Packit |
857059 |
return (void*)pList;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
} // End of procElementBeg()
|
|
Packit |
857059 |
|
|
Packit |
857059 |
|
|
Packit |
857059 |
/*******************************************************************************
|
|
Packit |
857059 |
*
|
|
Packit |
857059 |
* procElementEnd()
|
|
Packit |
857059 |
*
|
|
Packit |
857059 |
* Description:
|
|
Packit |
857059 |
* Process end element specification. Check for whether element is being
|
|
Packit |
857059 |
* extracted, whether element suppresses extraction, or neither. If the
|
|
Packit |
857059 |
* element being ended is an extraction element and is the outermost enclosing
|
|
Packit |
857059 |
* element for a group of extraction elements, output an extraction record.
|
|
Packit |
857059 |
*
|
|
Packit |
857059 |
* Inputs:
|
|
Packit |
857059 |
* pParserState - Pointer to IXml parser state
|
|
Packit |
857059 |
* pField - Pointer to field
|
|
Packit |
857059 |
* pObject - Pointer to object
|
|
Packit |
857059 |
* pParent - Pointer to element parent
|
|
Packit |
857059 |
* pValue - Pointer to element value (NULL terminated)
|
|
Packit |
857059 |
* length - Length of value
|
|
Packit |
857059 |
* ppAttrib - Pointer to pointer to element attribute data
|
|
Packit |
857059 |
* flValid - Valid flag
|
|
Packit |
857059 |
*
|
|
Packit |
857059 |
* Outputs:
|
|
Packit |
857059 |
* none
|
|
Packit |
857059 |
*/
|
|
Packit |
857059 |
void procElementEnd( IXmlParserState_t *pParserState, const IXML_FIELD *pField,
|
|
Packit |
857059 |
void *pObject, void *pParent, XML_Char *pValue, unsigned length,
|
|
Packit |
857059 |
boolean flValid )
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
int ix;
|
|
Packit |
857059 |
ELEMENT_TABLE_ENTRY *pElement = NULL;
|
|
Packit |
857059 |
ELEMENT_LIST* pList = (ELEMENT_LIST*)pObject;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
if (pList)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
// this tag Matched one or more elements
|
|
Packit |
857059 |
int i;
|
|
Packit |
857059 |
for (i=0; i<pList->numElements; i++)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
ix = pList->Elements[i].ix;
|
|
Packit |
857059 |
ASSERT(ix >= 0);
|
|
Packit |
857059 |
pElement = &tbElements[ix];
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// Check for extracted element
|
|
Packit |
857059 |
if (ix < numElementsExtract)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
// Check for suppression, ignore matches within suppression
|
|
Packit |
857059 |
if (ctElementsSuppress == 0)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
// matched extraction element
|
|
Packit |
857059 |
if (!pElement->pAttrName || pElement->pAttrValue)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
// operate on element value
|
|
Packit |
857059 |
ProcessMatchedElement( pElement, pValue, length,
|
|
Packit |
857059 |
levelParse );
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
} // End of if (ctElementsSuppress == 0)
|
|
Packit |
857059 |
|
|
Packit |
857059 |
} // End of if (ix < numElementsExtract)
|
|
Packit |
857059 |
else
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
// Suppress extraction element
|
|
Packit |
857059 |
ctElementsSuppress--;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
if (pList->Elements[i].pAttrValue)
|
|
Packit |
857059 |
free(pList->Elements[i].pAttrValue);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
} // End of for (i=0; i<pList->numElements; i++)
|
|
Packit |
857059 |
free(pList);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
} // End of if (pList)
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// Merge current element change flag into last change flag
|
|
Packit |
857059 |
if (!ctElementsSuppress)
|
|
Packit |
857059 |
flElementChangeLast |= flElementChange;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
flElementChange = FALSE;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// Check for end of element which encloses extracted element(s)
|
|
Packit |
857059 |
for (ix = 0; ix < numElementsExtract; ix++)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
if (tbElements[ix].level > levelParse)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
dispExtractionRecord();
|
|
Packit |
857059 |
tbElements[ix].lenValue = -tbElements[ix].lenValue;
|
|
Packit |
857059 |
tbElements[ix].pValue[0] = 0;
|
|
Packit |
857059 |
tbElements[ix].level = 0;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
levelParse--;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
} // End of procElementEnd()
|
|
Packit |
857059 |
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// End of file
|
|
Packit |
857059 |
|