⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xmlfile.cpp.svn-base

📁 wince c++ 下 开发的 rss 阅读器源代码
💻 SVN-BASE
📖 第 1 页 / 共 2 页
字号:
	}
	else
		return _T("");
}

CString CXmlNode::GetXML() {
	CString strXML;
	POSITION pos = GetFirstChildPos();
	while (pos != NULL) {
		CXmlNode *child = GetNextChild(pos);

		CString sName, sAttrs;
		CString sTag;
		POSITION posAttr;
		switch (child->GetType()) {
			case CXmlNode::Tag:
				sAttrs.Empty();
				posAttr = child->Attrs.GetHeadPosition();
				while (posAttr != NULL) {
					CXmlAttr *attr = child->Attrs.GetNext(posAttr);
					CString strPair;
					strPair.Format(_T(" %s=\"%s\""), attr->GetName(), attr->GetValue());
					sAttrs += strPair;
				}

				sName = child->GetName();
				if (child->GetChildCount() > 0) {
					sTag.Format(_T("<%s%s>%s</%s>"), sName, sAttrs, child->GetXML(), sName);
				}
				else {
					sTag.Format(_T("<%s%s/>"), sName, sAttrs);
				}
				strXML += sTag;
				break;

			case CXmlNode::Data:
				strXML += child->Text;
				break;
		}
	}

	strXML.TrimLeft();
	strXML.TrimRight();
	return strXML;
}

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CXmlFile::CXmlFile() {
	RootNode = NULL;
	Encoding = NULL;

	TempNode = NULL;
}

CXmlFile::~CXmlFile() {
	delete RootNode;
	if (Encoding != NULL) delete [] Encoding;
}

void CXmlFile::OnStartElement(const char *name, const char **attr) {
//	LOG1(1, "OnStart('%s')", name);

	CString sName = CharToWChar(name);
	CList<CXmlAttr*, CXmlAttr*> arAttrs;
	// create array of attributes
	for (int i = 0; attr[i]; i += 2)
		arAttrs.AddTail(new CXmlAttr(CharToWChar(attr[i]), CharToWChar(attr[i + 1], CP_UTF8)));
	CXmlNode *newNode = new CXmlNode(CXmlNode::Tag, TempNode, sName, arAttrs);

	if (RootNode == NULL)
		RootNode = newNode;
	else {
//	if (TempNode != NULL) {
		CString temp = TempValue;
		temp.TrimLeft();
		temp.TrimRight();
		if (!temp.IsEmpty()) {
			TempNode->AddChild(new CXmlNode(CXmlNode::Data, TempNode, TempValue));
		}
		TempNode->AddChild(newNode);
	}

	TempNode = newNode;
	TempValue.Empty();
}

void CXmlFile::OnEndElement(const char *name) {
//	LOG1(1, "OnEnd('%s')", name);

	if (TempNode != NULL) {
		CXmlNode *node = new CXmlNode(CXmlNode::Data, TempNode, TempValue);
		TempNode->AddChild(node);
		TempNode = TempNode->GetParentNode();
	}
	TempValue.Empty();
}

void CXmlFile::OnCharacterData(const char *name, int len) {
//	LOG1(1, "CXmlFile::OnCharacterData(, %d)", len);

	int wLen = MultiByteToWideChar(CP_UTF8, 0, name, len, NULL, 0);
	CString s;
	LPTSTR wStr = s.GetBufferSetLength(wLen);
	MultiByteToWideChar(CP_UTF8, 0, name, len, wStr, wLen);
	TempValue += s;
}

/*void CXmlFile::OnDefault(const XML_Char *s, int len) {
	LOG1(1, "CXmlFile::OnDefault(, %d)", len);

	char *n = new char [len + 1];
	strncpy(n, s, len);
	n[len] = '\0';
	LOG1(1, "D: '%s'", n);
	delete [] n;
}
*/

void CXmlFile::OnDeclaration(const XML_Char *version, const XML_Char *encoding, int standalone) {
	LOG3(7, "CXmlFile::OnDeclaration('%s', '%s', %d)", version, encoding, standalone);

	if (Encoding != NULL) delete [] Encoding;
	if (encoding != NULL) {
		Encoding = DuplicateString(encoding);
		_strlwr(Encoding);

		// crippling pRSSreader: some sites reports iso-8859-1 but they use cp1252 (it is common, to
		// treat iso-8859-1 encoded files as cp-1252)
		if (strcmp(Encoding, "iso-8859-1") == 0) {
			delete [] Encoding;
			Encoding = DuplicateString("windows-1252");
		}
	}
	else {
		Encoding = DuplicateString(DefaultEncoding);
		_strlwr(Encoding);
	}
}

int CXmlFile::GetBomLen(char *buffer) {
	if (strncmp(buffer, "\x00\x00\xFE\xFF", 4) == 0) return 4;			// UTF-32 big-endian
	else if (strncmp(buffer, "\xFF\xFE\x00\x00", 4) == 0) return 4;	// UTF-32 little-endian
	else if (strncmp(buffer, "\xFE\xFF", 2) == 0) return 2;			// UTF-16 big-endian
	else if (strncmp(buffer, "\xFF\xFE", 2) == 0) return 2;				// UTF-16 little-endian
	else if (strncmp(buffer, "\xEF\xBB\xBF", 3) == 0) return 3;			// UTF-8
	else return 0;
}

#define BUFSIZ					16384

// tries to determine XML document encoding from buffer
BOOL CXmlFile::DetermineEncoding(char buffer[], int len) {
	LOG0(7, "CXmlFile::DetermineEncoding(, )");

	XML_Parser parser;

	parser = XML_ParserCreate(NULL);
	XML_SetUserData(parser, this);
	XML_SetXmlDeclHandler(parser, declHandler);
	XML_SetElementHandler(parser, NULL, NULL);
	XML_SetCharacterDataHandler(parser, NULL);
	XML_SetUnknownEncodingHandler(parser, NULL, 0);

	// set default encoding
	if (Encoding != NULL) delete [] Encoding;
	Encoding = DuplicateString(DefaultEncoding);

	BOOL done = FALSE;
	XML_Parse(parser, buffer, len, done);

	XML_ParserFree(parser);

	delete RootNode;
	RootNode = TempNode = NULL;

	return TRUE;
}

BOOL CXmlFile::LoadFromFile(LPCTSTR fileName) {
	LOG1(5, "CXmlFile::LoadFromFile('%S')", fileName);

	char buf[BUFSIZ];
	BOOL done;
	int depth = 0;

	HANDLE hFile = CreateFile(fileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
	if (hFile == INVALID_HANDLE_VALUE) {
		return FALSE;
	}

	delete RootNode;
	RootNode = TempNode = NULL;

	int bomLen = 0;
	// first get the encoding
	// load first 8K (should be enough to determine the encoding)
	DWORD read = 0;
	if (ReadFile(hFile, buf, BUFSIZ, &read, NULL)) {
		bomLen = GetBomLen(buf);
		if (!DetermineEncoding(buf + bomLen, BUFSIZ))
			return FALSE;
	}
	else
		return FALSE;

	BOOL ret = TRUE;

	XML_Parser parser = XML_ParserCreate("prssr");
	XML_SetUserData(parser, this);
	XML_SetXmlDeclHandler(parser, NULL);
	XML_SetElementHandler(parser, startElement, endElement);
	XML_SetCharacterDataHandler(parser, charDataHandler);
	XML_SetUnknownEncodingHandler(parser, unknownEncoding, this);

	SetFilePointer(hFile, bomLen, NULL, FILE_BEGIN);
	// main load loop with the parsing
	do {
		DWORD read;
		done = FALSE;
		if (ReadFile(hFile, buf, BUFSIZ, &read, NULL)) {
			done = read < BUFSIZ;
			if (XML_Parse(parser, buf, read, done) == XML_STATUS_ERROR) {
				LOG2(1, "Error: %s at line %d",
					XML_ErrorString(XML_GetErrorCode(parser)),
					XML_GetCurrentLineNumber(parser));
				ret = FALSE;

				delete RootNode;
				RootNode = TempNode = NULL;
				break;
			}
		}
	} while (!done);

	CloseHandle(hFile);

//	RootNode = TempNode;
	TempNode = NULL;

	XML_ParserFree(parser);

	return ret;
}

#if defined PRSSR_APP

BOOL CXmlFile::LoadFromMemory(char buffer[], int len) {
	LOG0(7, "CXmlFile::LoadFromMemory()");

	int depth = 0;

	delete RootNode;
	RootNode = TempNode = NULL;

	int bomLen = GetBomLen(buffer);		// FIXME: if buffer is small and no BOM is present
	// first get the encoding
	if (!DetermineEncoding(buffer + bomLen, min(BUFSIZ, len)))
		return FALSE;
//	LOG1(7, "Encoding ('%S')", Encoding);

	XML_Parser parser = XML_ParserCreate("prssr");
	XML_SetUserData(parser, this);
	XML_SetXmlDeclHandler(parser, NULL);
	XML_SetElementHandler(parser, startElement, endElement);
	XML_SetCharacterDataHandler(parser, charDataHandler);
	XML_SetUnknownEncodingHandler(parser, unknownEncoding, this);

	BOOL ret = TRUE;
	// main load loop with the parsing
	BOOL done = FALSE;
	if (XML_Parse(parser, buffer + bomLen, len, done) == XML_STATUS_ERROR) {
		LOG2(7, "Error: %s at line %d",
			XML_ErrorString(XML_GetErrorCode(parser)),
			XML_GetCurrentLineNumber(parser));
		ret = FALSE;

		delete RootNode;
		RootNode = TempNode = NULL;
	}
	else {
//		RootNode = TempNode;
		TempNode = NULL;
	}

	XML_ParserFree(parser);

	return ret;
}


CString CXmlFile::FormatAttributeValue(const CString &value) {
	CString s = value;
	s.Replace(_T("&"), _T("&amp;"));
	s.Replace(_T("<"), _T("&lt;"));
	s.Replace(_T("\""), _T("&quot;"));
	s.Replace(_T(">"), _T("&gt;"));

	s.Replace(_T("\t"), _T("&#9"));
	s.Replace(_T("\n"), _T("&#10"));
	s.Replace(_T("\r"), _T("&#13"));

	return s;
}

BOOL CXmlFile::SaveNode(CBufferedFile &file, CXmlNode *node) {
	static int depth = 0;

	CString indent;
	if (depth > 0)
		indent = CString('\t', depth);

	CString sAttrs;
	POSITION posAttr = node->GetFirstAttrPos();
	while (posAttr != NULL) {
		CXmlAttr *attr = node->GetNextAttr(posAttr);
		CString sA;
		sA.Format(_T(" %s=\"%s\""), attr->GetName(), FormatAttributeValue(attr->GetValue()));
		sAttrs += sA;
	}

	BOOL ret = TRUE;

	CString tag;
	if (node->GetValue().GetLength() == 0 && node->GetChildCount() == 0) {
		// just to have nice output
		if (sAttrs.GetLength() > 0)
			sAttrs += ' ';

		ret = ret ? WriteFileString(file, indent, CP_UTF8) : FALSE;
		tag.Format(_T("<%s%s/>\n"), node->GetName(), sAttrs);
		ret = ret ? WriteFileString(file, tag, CP_UTF8) : FALSE;
	}
	else {
		// openning tag
		ret = ret ? WriteFileString(file, indent, CP_UTF8) : FALSE;
		tag.Format(_T("<%s%s>\n"), node->GetName(), sAttrs);
		ret = ret ? WriteFileString(file, tag, CP_UTF8) : FALSE;

		if (ret) {
			// FIXME: saving the value of the tag
			depth++;
			POSITION pos = node->GetFirstChildPos();
			while (pos != NULL) {
				CXmlNode *child = node->GetNextChild(pos);
				if (!SaveNode(file, child)) {
					ret = FALSE;
					break;
				}
			}
			depth--;
		}

		// closing tag
		ret = ret ? WriteFileString(file, indent, CP_UTF8) : FALSE;
		tag.Format(_T("</%s>\n"), node->GetName());
		ret = ret ? WriteFileString(file, tag, CP_UTF8) : FALSE;
	}

	return ret;
}


BOOL CXmlFile::Save(LPCTSTR fileName) {
	CBufferedFile file;
	if (file.Create(fileName, GENERIC_WRITE, 0, CREATE_ALWAYS, 0)) {
		BOOL ret = TRUE;

		// save xml header
		CString hdr;
		hdr.Format(_T("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"));
		ret = ret ? WriteFileString(file, hdr, CP_UTF8) : FALSE;

		// save xml
		ret = ret ? SaveNode(file, RootNode) : FALSE;

		file.Close();

		return ret;
	}
	else
		return FALSE;
}

#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -