void Bookmark::Load(const XMLNode& node)
{
	if (MakeCString(node.tagName) != pszTagBookmark)
		return;

	wstring str;
	if (node.GetAttribute(pszAttrTitle, str))
		strTitle = MakeUTF8String(str);

	node.GetIntAttribute(pszAttrType, nLinkType);

	if (nLinkType == URL)
	{
		if (node.GetAttribute(pszAttrURL, str))
			strURL = MakeUTF8String(str);
	}
	else if (nLinkType == Page || nLinkType == View)
	{
		node.GetIntAttribute(pszAttrPage, nPage);
		if (nLinkType == View)
		{
			node.GetLongAttribute(pszAttrOffsetX, ptOffset.x);
			node.GetLongAttribute(pszAttrOffsetY, ptOffset.y);

			int nMargin;
			if (node.GetIntAttribute(pszAttrMargin, nMargin))
				bMargin = (nMargin != 0);
		}
	}

	list<XMLNode>::const_iterator it;
	for (it = node.childElements.begin(); it != node.childElements.end(); ++it)
	{
		const XMLNode& child = *it;
		if (MakeCString(child.tagName) == pszTagBookmark)
		{
			children.push_back(Bookmark());
			Bookmark& bookmark = children.back();
			bookmark.Load(child);
		}
	}
}
XLIFFFile*
XLIFFFile::Parse(const string& filename)
{
    XLIFFFile* result = new XLIFFFile();

    XMLNode* root = NodeHandler::ParseFile(filename, XMLNode::PRETTY);
    if (root == NULL) {
        return NULL;
    }

    // <file>
    vector<XMLNode*> files = root->GetElementsByName(XLIFF_XMLNS, "file");
    for (size_t i=0; i<files.size(); i++) {
        XMLNode* file = files[i];

        string datatype = file->GetAttribute("", "datatype", "");
        string originalFile = file->GetAttribute("", "original", "");

        Configuration sourceConfig;
        sourceConfig.locale = file->GetAttribute("", "source-language", "");
        result->m_sourceConfig = sourceConfig;

        Configuration targetConfig;
        targetConfig.locale = file->GetAttribute("", "target-language", "");
        result->m_targetConfig = targetConfig;

        result->m_currentVersion = file->GetAttribute("", "build-num", "");
        result->m_oldVersion = "old";

        // <body>
        XMLNode* body = get_unique_node(file, XLIFF_XMLNS, "body", true);
        if (body == NULL) continue;

        // <trans-unit>
        vector<XMLNode*> transUnits = body->GetElementsByName(XLIFF_XMLNS, "trans-unit");
        for (size_t j=0; j<transUnits.size(); j++) {
            XMLNode* transUnit = transUnits[j];

            string rawID = transUnit->GetAttribute("", "id", "");
            if (rawID == "") {
                transUnit->Position().Error("<trans-unit> tag requires an id");
                continue;
            }
            string id;
            int index;

            if (!StringResource::ParseTypedID(rawID, &id, &index)) {
                transUnit->Position().Error("<trans-unit> has invalid id '%s'\n", rawID.c_str());
                continue;
            }

            // <source>
            XMLNode* source = get_unique_node(transUnit, XLIFF_XMLNS, "source", false);
            if (source != NULL) {
                XMLNode* node = source->Clone();
                node->SetPrettyRecursive(XMLNode::EXACT);
                result->AddStringResource(StringResource(source->Position(), originalFile,
                            sourceConfig, id, index, node, CURRENT_VERSION,
                            result->m_currentVersion));
            }

            // <target>
            XMLNode* target = get_unique_node(transUnit, XLIFF_XMLNS, "target", false);
            if (target != NULL) {
                XMLNode* node = target->Clone();
                node->SetPrettyRecursive(XMLNode::EXACT);
                result->AddStringResource(StringResource(target->Position(), originalFile,
                            targetConfig, id, index, node, CURRENT_VERSION,
                            result->m_currentVersion));
            }

            // <alt-trans>
            XMLNode* altTrans = get_unique_node(transUnit, XLIFF_XMLNS, "alt-trans", false);
            if (altTrans != NULL) {
                // <source>
                XMLNode* altSource = get_unique_node(altTrans, XLIFF_XMLNS, "source", false);
                if (altSource != NULL) {
                    XMLNode* node = altSource->Clone();
                    node->SetPrettyRecursive(XMLNode::EXACT);
                    result->AddStringResource(StringResource(altSource->Position(),
                                originalFile, sourceConfig, id, index, node, OLD_VERSION,
                                result->m_oldVersion));
                }

                // <target>
                XMLNode* altTarget = get_unique_node(altTrans, XLIFF_XMLNS, "target", false);
                if (altTarget != NULL) {
                    XMLNode* node = altTarget->Clone();
                    node->SetPrettyRecursive(XMLNode::EXACT);
                    result->AddStringResource(StringResource(altTarget->Position(),
                                originalFile, targetConfig, id, index, node, OLD_VERSION,
                                result->m_oldVersion));
                }
            }
        }
    }
    delete root;
    return result;
}
void Annotation::Load(const XMLNode& node)
{
	if (MakeCString(node.tagName) != pszTagAnnotation)
		return;

	int borderType;
	if (node.GetIntAttribute(pszAttrBorder, borderType))
	{
		if (borderType >= BorderNone && borderType <= BorderXOR)
			nBorderType = borderType;
	}

	COLORREF color;
	if (node.GetColorAttribute(pszAttrBorderColor, color))
		crBorder = color;

	int nHideBorder;
	if (node.GetIntAttribute(pszAttrBorderHideInactive, nHideBorder))
		bHideInactiveBorder = !!nHideBorder;

	int fillType;
	if (node.GetIntAttribute(pszAttrFill, fillType))
	{
		if (fillType >= FillNone && fillType <= FillXOR)
			nFillType = fillType;
	}

	if (node.GetColorAttribute(pszAttrFillColor, color))
		crFill = color;

	int nPercent;
	if (node.GetIntAttribute(pszAttrFillTransparency, nPercent))
	{
		if (nPercent >= 0 && nPercent <= 100)
			fTransparency = nPercent / 100.0;
	}

	int nHideFill;
	if (node.GetIntAttribute(pszAttrFillHideInactive, nHideFill))
		bHideInactiveFill = !!nHideFill;

	wstring str;
	if (node.GetAttribute(pszAttrComment, str))
		strComment = MakeUTF8String(str);

	int nShowComment;
	if (node.GetIntAttribute(pszAttrCommentAlwaysShow, nShowComment))
		bAlwaysShowComment = !!nShowComment;

	if (node.GetAttribute(pszAttrURL, str))
		strURL = MakeUTF8String(str);

	rects.clear();
	list<XMLNode>::const_iterator it;
	for (it = node.childElements.begin(); it != node.childElements.end(); ++it)
	{
		const XMLNode& child = *it;
		if (MakeCString(child.tagName) == pszTagRect)
		{
			GRect rect;
			if (!child.GetIntAttribute(pszAttrLeft, rect.xmin)
					|| !child.GetIntAttribute(pszAttrTop, rect.ymin)
					|| !child.GetIntAttribute(pszAttrRight, rect.xmax)
					|| !child.GetIntAttribute(pszAttrBottom, rect.ymax))
				continue;

			rects.push_back(rect);
		}
	}

	UpdateBounds();
}