* BUG: .XmlReader.Node.Attributes: Raise an error instead of segfault when an attribute does not exist
* NEW: .XmlReader.Node.Attributes.Exist() is a new method to check if an attribute is present
* BUG: XmlReader: Fix recognition of CDATA elements when their contents look like XML
* BUG: XmlReader: Correctly detect ending sequence of CDATA and comment sections (reset the recognition state when the sequence is interrupted)



git-svn-id: svn://localhost/gambas/trunk@8116 867c0c6c-44f3-4631-809d-bfa615b0a4ec
This commit is contained in:
Tobias Boege 2017-04-02 14:59:50 +00:00
parent 91518a2b72
commit 9b105f5f19
2 changed files with 50 additions and 14 deletions

View file

@ -141,10 +141,31 @@ if(!THIS->foundNode->type == Node::ElementNode) return;
Attribute *attr = XMLElement_GetAttribute((Element*)(THIS->foundNode), STRING(name), LENGTH(name));
if (!attr)
{
GB.Error("No such attribute");
return;
}
GB.ReturnNewString(attr->attrValue, attr->lenAttrValue);
END_METHOD
BEGIN_METHOD(CReaderNodeAttr_Exist, GB_STRING name)
if(!THIS->foundNode || THIS->state == READ_END_CUR_ELEMENT)
{
return;
}
if(!THIS->foundNode->type == Node::ElementNode) return;
Attribute *attr = XMLElement_GetAttribute((Element*)(THIS->foundNode), STRING(name), LENGTH(name));
GB.ReturnBoolean(!!attr);
END_METHOD
BEGIN_PROPERTY(CReaderNodeAttr_count)
if(!THIS->foundNode || THIS->state == READ_END_CUR_ELEMENT)
@ -353,6 +374,7 @@ GB_DESC CReaderNodeAttributesDesc[] =
GB_METHOD("_get", "s", CReaderNodeAttr_get, "(Name)s"),
GB_METHOD("_next", "s", CReaderNodeAttr_next, ""),
GB_METHOD("Exist", "b", CReaderNodeAttr_Exist, "(Name)s"),
GB_PROPERTY_READ("Count", "i", CReaderNodeAttr_count),
GB_PROPERTY_READ("Name", "i", CReaderNodeAttr_name),
GB_PROPERTY_READ("Value", "i", CReaderNodeAttr_value),

View file

@ -138,7 +138,21 @@ int Reader::ReadChar(char car)
return 0;
}
if(car == '<' && !inComment)//Début de tag
/* [T. Boege, 02 Apr 2017]: Reset specialTagLevel, which tries to recognise a sequence
* of characters, when this sequence is interrupted, so that e.g. <![CDATA[ab]x]>
* does *not* finish the CDATA tag at ]x]>. We want a literal ]]>. */
if (inCDATA)
{
if (specialTagLevel > CDATA_TAG_STARTCHAR_8 && car != ']' && car != '>')
specialTagLevel = CDATA_TAG_STARTCHAR_8;
}
if (inComment)
{
if (specialTagLevel > COMMENT_TAG_STARTCHAR_3 && car != '-' && car != '-')
specialTagLevel = COMMENT_TAG_STARTCHAR_3;
}
if(car == '<' && !inComment && !inCDATA)//Début de tag
{
if(inTag)//Si on est déjà dans un tag
{
@ -166,7 +180,7 @@ int Reader::ReadChar(char car)
return NODE_TEXT;
}
}
else if(car == '>' && inTag && !inEndTag && !inComment)//Fin de tag (de nouvel élément)
else if(car == '>' && inTag && !inEndTag && !inComment && !inCDATA)//Fin de tag (de nouvel élément)
{
DESTROYPARENT(foundNode);
//UNREF(foundNode);
@ -195,12 +209,12 @@ int Reader::ReadChar(char car)
this->state = NODE_ELEMENT;
return NODE_ELEMENT;
}
else if(isWhiteSpace(car) && inTag && inTagName && !inComment)// Fin de tagName
else if(isWhiteSpace(car) && inTag && inTagName && !inComment && !inCDATA)// Fin de tagName
{
inTagName = false;
XMLElement_RefreshPrefix((Element*)curNode);
}
else if(isNameStartChar(car) && inTag && !inTagName && !inEndTag && !inAttrVal && !inAttrName && !inComment)//Début de nom d'attribut
else if(isNameStartChar(car) && inTag && !inTagName && !inEndTag && !inAttrVal && !inAttrName && !inComment && !inCDATA)//Début de nom d'attribut
{
if(attrName && attrVal)
{
@ -220,16 +234,16 @@ int Reader::ReadChar(char car)
*attrName = car;
lenAttrName = 1;
}
else if(car == '=' && inAttrName && !inComment)//Fin du nom d'attribut
else if(car == '=' && inAttrName && !inComment && !inCDATA)//Fin du nom d'attribut
{
inAttrName = false;
}
else if((car == '\'' || car == '"') && inAttr && !inAttrVal && !inComment)//Début de valeur d'attribut
else if((car == '\'' || car == '"') && inAttr && !inAttrVal && !inComment && !inCDATA)//Début de valeur d'attribut
{
inAttrVal = true;
attrVal = 0;
}
else if((car == '\'' || car == '"') && inAttr && inAttrVal && !inComment)//Fin de valeur d'attribut
else if((car == '\'' || car == '"') && inAttr && inAttrVal && !inComment && !inCDATA)//Fin de valeur d'attribut
{
XMLElement_AddAttribute(((Element*)curNode), attrName, lenAttrName,
attrVal, lenAttrVal);
@ -240,7 +254,7 @@ int Reader::ReadChar(char car)
this->state = READ_ATTRIBUTE;
return READ_ATTRIBUTE;
}
else if(car == '/' && inTag && !inAttrVal && !inComment)//Self-closed element
else if(car == '/' && inTag && !inAttrVal && !inComment && !inCDATA)//Self-closed element
{
inTag = false;
inTagName = false;
@ -256,13 +270,13 @@ int Reader::ReadChar(char car)
depth++;
return NODE_ELEMENT;
}
else if(car == '/' && inNewTag && !inComment)//C'est un tag de fin
else if(car == '/' && inNewTag && !inComment && !inCDATA)//C'est un tag de fin
{
inEndTag = true;
inNewTag = false;
inTag = true;
}
else if(car == '>' && inEndTag && !inComment)//La fin d'un tag de fin
else if(car == '>' && inEndTag && !inComment && !inCDATA)//La fin d'un tag de fin
{
inTag = false;
inEndTag = false;
@ -350,7 +364,7 @@ int Reader::ReadChar(char car)
return NODE_CDATA;
}
//Caractère "-" de début de commentaire
else if(inCommentTag && car == '-' && specialTagLevel >= COMMENT_TAG_STARTCHAR_1 && specialTagLevel < COMMENT_TAG_STARTCHAR_3 && !inComment)
else if(inCommentTag && car == '-' && specialTagLevel >= COMMENT_TAG_STARTCHAR_1 && specialTagLevel < COMMENT_TAG_STARTCHAR_3 && !inComment && !inCDATA)
{
++specialTagLevel;
if (specialTagLevel == COMMENT_TAG_STARTCHAR_3)//Le tag <!-- est complet, on crée un nouveau node
@ -396,17 +410,17 @@ int Reader::ReadChar(char car)
return NODE_COMMENT;
}
//Début de prologue XML
else if(car == '?' && inNewTag && !inComment)
else if(car == '?' && inNewTag && !inComment && !inCDATA)
{
inXMLProlog = true;
inNewTag = false;
inTag = false;
}
else if(car == '?' && inXMLProlog && !inComment)
else if(car == '?' && inXMLProlog && !inComment && !inCDATA)
{
specialTagLevel = PROLOG_TAG_ENDCHAR;
}
else if(car == '>' && inXMLProlog && specialTagLevel == PROLOG_TAG_ENDCHAR && !inComment)
else if(car == '>' && inXMLProlog && specialTagLevel == PROLOG_TAG_ENDCHAR && !inComment && !inCDATA)
{
specialTagLevel = 0;
inXMLProlog = 0;