version 1.44.2.2, 2008/04/28 22:20:25
|
version 1.55.4.1, 2013/06/03 22:35:14
|
|
|
//%2006//////////////////////////////////////////////////////////////////////// |
//%LICENSE//////////////////////////////////////////////////////////////// |
// | // |
// Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development |
// Licensed to The Open Group (TOG) under one or more contributor license |
// Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems. |
// agreements. Refer to the OpenPegasusNOTICE.txt file distributed with |
// Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.; |
// this work for additional information regarding copyright ownership. |
// IBM Corp.; EMC Corporation, The Open Group. |
// Each contributor licenses this file to you under the OpenPegasus Open |
// Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.; |
// Source License; you may not use this file except in compliance with the |
// IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group. |
// License. |
// Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.; |
// |
// EMC Corporation; VERITAS Software Corporation; The Open Group. |
// Permission is hereby granted, free of charge, to any person obtaining a |
// Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.; |
// copy of this software and associated documentation files (the "Software"), |
// EMC Corporation; Symantec Corporation; The Open Group. |
// to deal in the Software without restriction, including without limitation |
// |
// the rights to use, copy, modify, merge, publish, distribute, sublicense, |
// Permission is hereby granted, free of charge, to any person obtaining a copy |
// and/or sell copies of the Software, and to permit persons to whom the |
// of this software and associated documentation files (the "Software"), to |
// Software is furnished to do so, subject to the following conditions: |
// deal in the Software without restriction, including without limitation the |
// |
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or |
// The above copyright notice and this permission notice shall be included |
// sell copies of the Software, and to permit persons to whom the Software is |
// in all copies or substantial portions of the Software. |
// furnished to do so, subject to the following conditions: |
// |
// |
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
// THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN |
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
// ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED |
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. |
// "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT |
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY |
// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR |
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, |
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT |
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE |
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN |
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
|
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
|
// | // |
//============================================================================== |
////////////////////////////////////////////////////////////////////////// |
// | // |
//%///////////////////////////////////////////////////////////////////////////// | //%///////////////////////////////////////////////////////////////////////////// |
| |
|
|
char replacement; | char replacement; |
}; | }; |
| |
// ATTN: Add support for more entity references |
|
static EntityReference _references[] = |
|
{ |
|
{ "&", 5, '&' }, |
|
{ "<", 4, '<' }, |
|
{ ">", 4, '>' }, |
|
{ """, 6, '"' }, |
|
{ "'", 6, '\'' } |
|
}; |
|
|
|
|
|
// Implements a check for a whitespace character, without calling | // Implements a check for a whitespace character, without calling |
// isspace( ). The isspace( ) function is locale-sensitive, | // isspace( ). The isspace( ) function is locale-sensitive, |
// and incorrectly flags some chars above 0x7f as whitespace. This | // and incorrectly flags some chars above 0x7f as whitespace. This |
|
|
return CharSet::isXmlWhiteSpace((Uint8)c); | return CharSet::isXmlWhiteSpace((Uint8)c); |
} | } |
| |
static Uint32 _REFERENCES_SIZE = (sizeof(_references) / sizeof(_references[0])); |
|
| |
//////////////////////////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////////////////////////// |
// | // |
|
|
const String& message) | const String& message) |
{ | { |
String dftMsg = _xmlMessages[Uint32(code) - 1]; | String dftMsg = _xmlMessages[Uint32(code) - 1]; |
String key = _xmlKeys[Uint32(code) - 1]; |
const char* key = _xmlKeys[Uint32(code) - 1]; |
String msg = message; | String msg = message; |
| |
dftMsg.append(": on line $0"); | dftMsg.append(": on line $0"); |
|
|
dftMsg.append("$1"); | dftMsg.append("$1"); |
} | } |
| |
return MessageLoaderParms(key, dftMsg, line ,msg); |
return MessageLoaderParms(key, dftMsg.getCString(), line ,msg); |
} | } |
| |
static MessageLoaderParms _formPartialMessage(Uint32 code, Uint32 line) | static MessageLoaderParms _formPartialMessage(Uint32 code, Uint32 line) |
{ | { |
String dftMsg = _xmlMessages[Uint32(code) - 1]; | String dftMsg = _xmlMessages[Uint32(code) - 1]; |
String key = _xmlKeys[Uint32(code) - 1]; |
const char* key = _xmlKeys[Uint32(code) - 1]; |
| |
dftMsg.append(": on line $0"); | dftMsg.append(": on line $0"); |
| |
return MessageLoaderParms(key, dftMsg, line); |
return MessageLoaderParms(key, dftMsg.getCString(), line); |
} | } |
| |
| |
|
|
// | // |
//////////////////////////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////////////////////////// |
| |
XmlParser::XmlParser(char* text, XmlNamespace* ns) |
XmlParser::XmlParser(char* text, XmlNamespace* ns, Boolean hideEmptyTags) |
: _line(1), | : _line(1), |
_current(text), | _current(text), |
_restoreChar('\0'), | _restoreChar('\0'), |
_foundRoot(false), | _foundRoot(false), |
_supportedNamespaces(ns), | _supportedNamespaces(ns), |
// Start valid indexes with -2. -1 is reserved for not found. | // Start valid indexes with -2. -1 is reserved for not found. |
_currentUnsupportedNSType(-2) |
_currentUnsupportedNSType(-2), |
|
_hideEmptyTags(hideEmptyTags) |
{ | { |
} | } |
| |
|
|
#pragma optimize( "", on ) | #pragma optimize( "", on ) |
#endif | #endif |
| |
static inline int _getCharRef(char*& p, bool hex) |
static inline int _getCharRef(char*& p) |
{ | { |
char* end; | char* end; |
unsigned long ch; | unsigned long ch; |
|
Boolean hex = false; |
| |
if (hex) |
if (*p == 'x') |
{ | { |
ch = strtoul(p, &end, 16); |
hex = true; |
|
ch = strtoul(++p, &end, 16); |
} | } |
else | else |
{ | { |
|
|
return ch; | return ch; |
} | } |
| |
static void _normalize(Uint32& line, char*& p, char end_char, char*& start) |
// Parse an entity reference or a character reference |
|
static inline int _getRef(Uint32 line, char*& p) |
{ | { |
// Skip over leading whitespace: |
int ch; |
| |
_skipWhitespace(line, p); |
if (*p == '#') |
start = p; |
{ |
|
ch = _getCharRef(++p); |
|
} |
|
else |
|
{ |
|
ch = _getEntityRef(p); |
|
} |
|
|
|
if (ch == -1) |
|
{ |
|
throw XmlException(XmlException::MALFORMED_REFERENCE, line); |
|
} |
| |
|
return ch; |
|
} |
|
|
|
static inline void _normalizeElementValue( |
|
Uint32& line, |
|
char*& p, |
|
Uint32 &textLen) |
|
{ |
// Process one character at a time: | // Process one character at a time: |
| |
char* q = p; | char* q = p; |
|
char *start = p; |
| |
while (*p && (*p != end_char)) |
while (*p && (*p != '<')) |
{ | { |
if (_isspace(*p)) | if (_isspace(*p)) |
{ | { |
// Compress sequences of whitespace characters to a single space |
// Trim whitespace from the end of the value, but do not compress |
// character. Update line number when newlines encountered. |
// whitespace within the value. |
|
|
|
const char* start = p; |
| |
if (*p++ == '\n') | if (*p++ == '\n') |
{ | { |
line++; | line++; |
} | } |
| |
*q++ = ' '; |
|
|
|
_skipWhitespace(line, p); | _skipWhitespace(line, p); |
} |
|
else if (*p == '&') |
|
{ |
|
// Process entity characters and entity references: |
|
| |
p++; |
if (*p && (*p != '<')) |
int ch; |
|
|
|
if (*p == '#') |
|
{ | { |
*p++; |
// Transfer internal whitespace to q without compressing it. |
|
const char* i = start; |
if (*p == 'x') |
while (i < p) |
{ | { |
p++; |
*q++ = *i++; |
ch = _getCharRef(p, true); |
} |
} | } |
else | else |
{ | { |
ch = _getCharRef(p, false); |
// Do not transfer trailing whitespace to q. |
|
break; |
} | } |
} | } |
|
else if (*p == '&') |
|
{ |
|
// Process an entity reference or a character reference. |
|
|
|
*q++ = _getRef(line, ++p); |
|
} |
else | else |
{ | { |
ch = _getEntityRef(p); |
*q++ = *p++; |
|
} |
} | } |
| |
if (ch == -1) |
// If q got behind p, it is safe and necessary to null-terminate q |
|
|
|
if (q != p) |
{ | { |
throw XmlException(XmlException::MALFORMED_REFERENCE, line); |
*q = '\0'; |
|
} |
|
textLen = (Uint32)(q - start); |
|
} |
|
|
|
static inline void _normalizeAttributeValue( |
|
Uint32& line, |
|
char*& p, |
|
char end_char, |
|
char*& start) |
|
{ |
|
// Skip over leading whitespace: |
|
|
|
_skipWhitespace(line, p); |
|
start = p; |
|
|
|
// Process one character at a time: |
|
|
|
char* q = p; |
|
|
|
while (*p && (*p != end_char)) |
|
{ |
|
if (_isspace(*p)) |
|
{ |
|
// Compress sequences of whitespace characters to a single space |
|
// character. Update line number when newlines encountered. |
|
|
|
if (*p++ == '\n') |
|
{ |
|
line++; |
|
} |
|
|
|
*q++ = ' '; |
|
|
|
_skipWhitespace(line, p); |
} | } |
|
else if (*p == '&') |
|
{ |
|
// Process an entity reference or a character reference. |
| |
*q++ = ch; |
*q++ = _getRef(line, ++p); |
} | } |
else | else |
{ | { |
|
|
} | } |
} | } |
| |
Boolean XmlParser::next( |
Boolean XmlParser::_next( |
XmlEntry& entry, | XmlEntry& entry, |
Boolean includeComment) | Boolean includeComment) |
{ | { |
|
|
{ | { |
// Normalize the content: | // Normalize the content: |
| |
char* start; |
char* start = _current; |
_normalize(_line, _current, '<', start); |
Uint32 textLen; |
|
_normalizeElementValue(_line, _current, textLen); |
| |
// Get the content: | // Get the content: |
| |
entry.type = XmlEntry::CONTENT; | entry.type = XmlEntry::CONTENT; |
entry.text = start; | entry.text = start; |
|
entry.textLen = textLen; |
| |
// Overwrite '<' with a null character (temporarily). | // Overwrite '<' with a null character (temporarily). |
| |
|
|
return true; | return true; |
} | } |
| |
|
Boolean XmlParser::next(XmlEntry& entry, Boolean includeComment) |
|
{ |
|
if (_hideEmptyTags) |
|
{ |
|
// Get the next tag. |
|
|
|
if (!_next(entry, includeComment)) |
|
return false; |
|
|
|
// If an EMPTY_TAG is encountered, then convert it to a START_TAG and |
|
// push a matching END_TAG on the put-back stack. This hides every |
|
// EMPTY_TAG from the caller. |
|
|
|
if (entry.type == XmlEntry::EMPTY_TAG) |
|
{ |
|
entry.type = XmlEntry::START_TAG; |
|
|
|
XmlEntry tmp; |
|
tmp.type = XmlEntry::END_TAG; |
|
tmp.text = entry.text; |
|
tmp.nsType = entry.nsType; |
|
tmp.localName = entry.localName; |
|
|
|
_putBackStack.push(tmp); |
|
} |
|
|
|
return true; |
|
} |
|
else |
|
return _next(entry, includeComment); |
|
} |
|
|
// Get the namespace type of the given tag | // Get the namespace type of the given tag |
int XmlParser::_getNamespaceType(const char* tag) | int XmlParser::_getNamespaceType(const char* tag) |
{ | { |
|
|
1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, | 1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, |
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, |
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, |
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, |
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, |
}; | }; |
| |
inline Boolean _getQName(char*& p, const char*& localName) | inline Boolean _getQName(char*& p, const char*& localName) |
|
|
| |
p++; | p++; |
| |
while (*p && _isInnerElementChar[Uint8(*p)]) |
// No explicit test for NULL termination is needed. |
|
// On position 0 of the array false is returned. |
|
while (_isInnerElementChar[Uint8(*p)]) |
p++; | p++; |
| |
// We've validated the prefix, now validate the local name | // We've validated the prefix, now validate the local name |
|
|
return false; | return false; |
| |
p++; | p++; |
|
// No explicit test for NULL termination is needed. |
while (*p && _isInnerElementChar[Uint8(*p)]) |
// On position 0 of the array false is returned. |
|
while (_isInnerElementChar[Uint8(*p)]) |
p++; | p++; |
} | } |
| |
|
|
entry.type = XmlEntry::XML_DECLARATION; | entry.type = XmlEntry::XML_DECLARATION; |
entry.text = ++p; | entry.text = ++p; |
| |
Boolean openCloseElement = false; |
|
|
|
if (_getElementName(p, entry.localName)) | if (_getElementName(p, entry.localName)) |
return; | return; |
} | } |
|
|
entry.type = XmlEntry::CDATA; | entry.type = XmlEntry::CDATA; |
entry.text = p; | entry.text = p; |
_getCData(p); | _getCData(p); |
|
entry.textLen = strlen(entry.text); |
return; | return; |
} | } |
else if (memcmp(p, "DOCTYPE", 7) == 0) | else if (memcmp(p, "DOCTYPE", 7) == 0) |
|
|
| |
return; | return; |
} | } |
else if ((((*p >= 'A') && (*p <= 'Z')) || |
else if (CharSet::isAlphaUnder(Uint8(*p))) |
((*p >= 'a') && (*p <= 'z')) || |
|
(*p == '_'))) |
|
{ | { |
entry.type = XmlEntry::START_TAG; | entry.type = XmlEntry::START_TAG; |
entry.text = p; | entry.text = p; |
|
|
char quote = *p++; | char quote = *p++; |
| |
char* start; | char* start; |
_normalize(_line, p, quote, start); |
_normalizeAttributeValue(_line, p, quote, start); |
attr.value = start; | attr.value = start; |
| |
if (*p != quote) | if (*p != quote) |
|
|
} | } |
| |
const XmlAttribute* XmlEntry::findAttribute( | const XmlAttribute* XmlEntry::findAttribute( |
int nsType, |
int attrNsType, |
const char* name) const | const char* name) const |
{ | { |
for (Uint32 i = 0, n = attributes.size(); i < n; i++) | for (Uint32 i = 0, n = attributes.size(); i < n; i++) |
{ | { |
if ((attributes[i].nsType == nsType) && |
if ((attributes[i].nsType == attrNsType) && |
(strcmp(attributes[i].localName, name) == 0)) | (strcmp(attributes[i].localName, name) == 0)) |
{ | { |
return &attributes[i]; | return &attributes[i]; |