📄 htmlparser.cpp
字号:
bool wxSimpleHtmlParser::IsAlpha(int ch)
{
return (wxIsalpha((wxChar) ch) != 0);
}
bool wxSimpleHtmlParser::IsWordChar(int ch)
{
return (wxIsalpha((wxChar) ch) != 0 || ch == wxT('-') || ch == wxT('_') || IsNumeric(ch));
}
bool wxSimpleHtmlParser::IsNumeric(int ch)
{
return (wxIsdigit((wxChar) ch) != 0 || ch == wxT('-') || ch == wxT('.')) ;
}
bool wxSimpleHtmlParser::IsCloseTagNeeded(const wxString &name)
{
if (name.IsSameAs(wxT("P"), false)) // e.g <P>
return false;
// ToDo add more items here.
return true;
}
// Encode/Decode Special Characters.
// See here for the used table: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/xmlsql/ac_xml1_1nqk.asp
/* static */ void wxSimpleHtmlParser::DecodeSpecialChars(wxString &value)
{
// XML translation
value.Replace(wxT(">"), wxT(">"), true);
value.Replace(wxT("<"), wxT("<"), true);
value.Replace(wxT("""), wxT("\""), true);
value.Replace(wxT("'"), wxT("'"), true);
value.Replace(wxT("&"), wxT("&"), true); // Note: do this as last to prevent replace problems.
}
/* static */ wxString wxSimpleHtmlParser::EncodeSpecialChars(const wxString &value)
{
wxString newvalue = value;
// XML translation
newvalue.Replace(wxT("&"), wxT("&"), true); // Note: do this as first to prevent replace problems.
newvalue.Replace(wxT(">"), wxT(">"), true);
newvalue.Replace(wxT("<"), wxT("<"), true);
newvalue.Replace(wxT("\""),wxT("""), true);
newvalue.Replace(wxT("'"), wxT("'"), true);
return newvalue;
}
// Matches this string (case insensitive)
bool wxSimpleHtmlParser::Matches(const wxString& tok, bool eatIt)
{
wxString text(m_text.Mid(m_pos, tok.Length()));
bool success = (text.CmpNoCase(tok) == 0) ;
if (success && eatIt)
{
m_pos += tok.Length();
}
return success;
}
// Safe way of getting a character
int wxSimpleHtmlParser::GetChar(size_t i) const
{
if (i >= (size_t) m_length)
return -1;
return m_text[i];
}
void wxSimpleHtmlParser::Clear()
{
if (m_topLevel)
delete m_topLevel;
m_topLevel = NULL;
m_text = wxEmptyString;
m_pos = 0;
m_length = 0;
}
// Write this file
void wxSimpleHtmlParser::Write(wxOutputStream& stream)
{
if (m_topLevel)
m_topLevel->Write(stream);
}
bool wxSimpleHtmlParser::WriteFile(wxString& filename)
{
wxFileOutputStream fstream(filename);
if (fstream.Ok())
{
Write(fstream);
return true;
}
else
return false;
}
/*
* wxSimpleHtmlTag
* Representation of a tag or chunk of text
*/
wxSimpleHtmlTag::wxSimpleHtmlTag(const wxString& tagName, int tagType)
{
m_name = tagName;
m_type = tagType;
m_attributes = NULL;
m_children = NULL;
m_parent = NULL;
m_next = NULL;
}
wxSimpleHtmlTag::~wxSimpleHtmlTag()
{
ClearAttributes();
ClearChildren();
}
//// Operations
void wxSimpleHtmlTag::ClearAttributes()
{
if (m_attributes)
{
wxSimpleHtmlAttribute* attr = m_attributes;
while (attr)
{
wxSimpleHtmlAttribute* next = attr->m_next;
attr->m_next = NULL;
delete attr;
attr = next;
}
m_attributes = NULL;
}
}
wxSimpleHtmlAttribute* wxSimpleHtmlTag::FindAttribute(const wxString& name) const
{
wxSimpleHtmlAttribute* attr = m_attributes;
while (attr)
{
if (attr->GetName().CmpNoCase(name) == 0)
{
return attr;
}
attr = attr->m_next;
}
return NULL;
}
void wxSimpleHtmlTag::AppendAttribute(const wxString& name, const wxString& value)
{
wxSimpleHtmlAttribute* attr = new wxSimpleHtmlAttribute(name, value);
if (m_attributes)
{
// Find tail
wxSimpleHtmlAttribute* last = m_attributes;
while (last->m_next)
last = last->m_next;
last->m_next = attr;
}
else
m_attributes = attr;
}
void wxSimpleHtmlTag::ClearChildren()
{
if (m_children)
{
wxSimpleHtmlTag* child = m_children;
while (child)
{
wxSimpleHtmlTag* next = child->m_next;
child->m_next = NULL;
delete child;
child = next;
}
m_children = NULL;
}
}
void wxSimpleHtmlTag::RemoveChild(wxSimpleHtmlTag *remove)
{
if (m_children)
{
wxSimpleHtmlTag* child = m_children;
wxSimpleHtmlTag* prev = NULL;
while (child)
{
wxSimpleHtmlTag* next = child->m_next;
if (child == remove)
{
child->m_next = NULL;
delete child;
if (prev != NULL)
prev->m_next = next;
else
m_children = next;
return;
}
prev = child;
child = next;
}
}
}
void wxSimpleHtmlTag::AppendTag(wxSimpleHtmlTag* tag)
{
if (!tag)
return;
if (m_children)
{
// Find tail
wxSimpleHtmlTag* last = m_children;
while (last->m_next)
last = last->m_next;
last->m_next = tag;
}
else
{
m_children = tag;
}
tag->m_parent = this;
}
void wxSimpleHtmlTag::AppendTagAfterUs(wxSimpleHtmlTag* tag)
{
if (!tag)
return;
tag->m_parent = m_parent;
tag->m_next = m_next;
m_next = tag;
}
// Gets the text from this tag and its descendants
wxString wxSimpleHtmlTag::GetTagText()
{
wxString text;
if (m_children)
{
wxSimpleHtmlTag* tag = m_children;
while (tag)
{
text += tag->GetTagText();
tag = tag->m_next;
}
return text;
}
else if (GetType() == wxSimpleHtmlTag_Text)
return GetText();
else
return wxEmptyString;
}
int wxSimpleHtmlTag::GetAttributeCount() const
{
int count = 0;
wxSimpleHtmlAttribute* attr = m_attributes;
while (attr)
{
count ++;
attr = attr->m_next;
}
return count;
}
wxSimpleHtmlAttribute* wxSimpleHtmlTag::GetAttribute(int i) const
{
int count = 0;
wxSimpleHtmlAttribute* attr = m_attributes;
while (attr)
{
if (count == i)
return attr;
count ++;
attr = attr->m_next;
}
return NULL;
}
int wxSimpleHtmlTag::GetChildCount() const
{
int count = 0;
wxSimpleHtmlTag* tag = m_children;
while (tag)
{
count ++;
tag = tag->m_next;
}
return count;
}
bool wxSimpleHtmlTag::HasAttribute(const wxString& name, const wxString& value) const
{
wxSimpleHtmlAttribute* attr = FindAttribute(name);
return (attr && (attr->GetValue().CmpNoCase(value) == 0)) ;
}
bool wxSimpleHtmlTag::HasAttribute(const wxString& name) const
{
return FindAttribute(name) != NULL ;
}
bool wxSimpleHtmlTag::GetAttributeValue(wxString& value, const wxString& attrName)
{
wxSimpleHtmlAttribute* attr = FindAttribute(attrName);
if (attr)
{
value = attr->GetValue();
return true;
}
else
return false;
}
// Search forward from this tag until we find a tag with this name & attribute
wxSimpleHtmlTag* wxSimpleHtmlTag::FindTag(const wxString& tagName, const wxString& attrName)
{
wxSimpleHtmlTag* tag = m_next;
while (tag)
{
if (tag->NameIs(tagName) && (attrName.IsEmpty() || tag->FindAttribute(attrName)))
return tag;
tag = tag->m_next;
}
return NULL;
}
bool wxSimpleHtmlTag::FindTextUntilTagClose(wxString& text, const wxString& tagName)
{
wxSimpleHtmlTag* tag = this;
while (tag)
{
if (tag->GetType() == wxSimpleHtmlTag_Close && tag->NameIs(tagName))
return true;
if (tag->GetType() == wxSimpleHtmlTag_Text)
text += tag->GetText();
tag = tag->m_next;
}
return true;
}
wxSimpleHtmlTag* wxSimpleHtmlTag::GetChild(int i) const
{
int count = 0;
wxSimpleHtmlTag* tag = m_children;
while (tag)
{
if (count == i)
return tag;
count ++;
tag = tag->m_next;
}
return NULL;
}
void wxSimpleHtmlTag::Write(wxOutputStream& stream)
{
// Some helpers to layout the open and close tags.
static bool sbUseTab = true;
static size_t snTabLevel = 0;
#if 0 // Enable if no tabs should be used to align the tags.
snTabLevel = 0;
#endif
// Handle the different types of tags we can write.
switch (GetType())
{
case wxSimpleHtmlTag_Text:
{
stream << wxSimpleHtmlParser::EncodeSpecialChars(m_text);
break;
}
case wxSimpleHtmlTag_Open:
{
size_t tab;
for(tab = 0; tab < snTabLevel; tab++)
stream << wxT("\t");
stream << wxT("<") << wxSimpleHtmlParser::EncodeSpecialChars(m_name);
if (GetAttributeCount() > 0)
stream << wxT(" ");
int i;
for (i = 0; i < GetAttributeCount(); i++)
{
wxSimpleHtmlAttribute* attr = GetAttribute(i);
attr->Write(stream);
if (i < GetAttributeCount() - 1)
stream << wxT(" ");
}
if(!m_children)
{
sbUseTab = false; // We're putting the open a close tag on the same line,
// so we don't wan't any tabs
stream << wxT(">");
}
else
{
// sbUseTab = true;
stream << wxT(">\n");
}
snTabLevel++;
break;
}
case wxSimpleHtmlTag_Directive:
{
stream << wxT("<!") << wxSimpleHtmlParser::EncodeSpecialChars(m_name) << wxT(" ");
int i;
for (i = 0; i < GetAttributeCount(); i++)
{
wxSimpleHtmlAttribute* attr = GetAttribute(i);
attr->Write(stream);
if (i < GetAttributeCount() - 1)
stream << wxT(" ");
}
stream << wxT(">\n");
break;
}
case wxSimpleHtmlTag_XMLDeclaration:
{
stream << wxT("<?") << wxSimpleHtmlParser::EncodeSpecialChars(m_name) << wxT(" ");
int i;
for (i = 0; i < GetAttributeCount(); i++)
{
wxSimpleHtmlAttribute* attr = GetAttribute(i);
attr->Write(stream);
if (i < GetAttributeCount() - 1)
stream << wxT(" ");
}
stream << wxT(">\n\n");
break;
}
case wxSimpleHtmlTag_Close:
{
if (snTabLevel) // Safety to prevent going around...
snTabLevel--; // Reduce the tab level
if (sbUseTab) // Do we write the open tag and close tag on a other line?
{
size_t tab;
for(tab = 0; tab < snTabLevel; tab++)
stream << wxT("\t");
}
stream << wxT("</") << wxSimpleHtmlParser::EncodeSpecialChars(m_name) << wxT(">\n");
sbUseTab = true;
break;
}
default:
{
break;
}
}
wxSimpleHtmlTag* tag = m_children;
while (tag)
{
tag->Write(stream);
tag = tag->m_next;
}
}
void wxSimpleHtmlAttribute::Write(wxOutputStream& stream)
{
if (m_value.IsEmpty())
stream << wxSimpleHtmlParser::EncodeSpecialChars(m_name);
else
{
stream << wxSimpleHtmlParser::EncodeSpecialChars(m_name);
stream << wxT("=\"");
stream << wxSimpleHtmlParser::EncodeSpecialChars(m_value);
stream << wxT("\"");
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -