TryGetXmlDocument ( String sUrl, RequestStatistics oRequestStatistics, out XmlDocument oXmlDocument, out XmlNamespaceManager oXmlNamespaceManager ) { Debug.Assert( !String.IsNullOrEmpty(sUrl) ); Debug.Assert(oRequestStatistics != null); AssertValid(); oXmlDocument = null; oXmlNamespaceManager = null; try { oXmlDocument = GetXmlDocument(sUrl, oRequestStatistics, out oXmlNamespaceManager); return (true); } catch (Exception oException) { if ( !HttpSocialNetworkUtil.ExceptionIsWebOrXml(oException)) { throw oException; } return (false); } }
TryGetXmlDocument ( String sUrl, RequestStatistics oRequestStatistics, out XmlDocument oXmlDocument ) { Debug.Assert(!String.IsNullOrEmpty(sUrl)); Debug.Assert(oRequestStatistics != null); AssertValid(); oXmlDocument = null; try { oXmlDocument = GetXmlDocument(sUrl, oRequestStatistics); return(true); } catch (Exception oException) { // Note: Because a FlickrException is also a WebException, the // following logic will cause false to be returned for a // FlickrException. if (!HttpSocialNetworkUtil.ExceptionIsWebOrXml(oException)) { throw oException; } return(false); } }
GetRelatedTagsRecursive ( String sTag, WhatToInclude eWhatToInclude, NetworkLevel eNetworkLevel, String sApiKey, Int32 iRecursionLevel, GraphMLXmlDocument oGraphMLXmlDocument, Dictionary <String, XmlNode> oTagDictionary, RequestStatistics oRequestStatistics ) { Debug.Assert(!String.IsNullOrEmpty(sTag)); Debug.Assert(eNetworkLevel == NetworkLevel.One || eNetworkLevel == NetworkLevel.OnePointFive || eNetworkLevel == NetworkLevel.Two); Debug.Assert(!String.IsNullOrEmpty(sApiKey)); Debug.Assert(iRecursionLevel == 1 || iRecursionLevel == 2); Debug.Assert(oGraphMLXmlDocument != null); Debug.Assert(oTagDictionary != null); Debug.Assert(oRequestStatistics != null); AssertValid(); /* * Here is what this method should do, based on the eNetworkLevel and * iRecursionLevel parameters. * * eNetworkLevel * |One | OnePointFive | Two * ---|------------------| ------------------| ----------------- * i 1 |Add all vertices. | Add all vertices. | Add all vertices. * R | | | * e |Add all edges. | Add all edges. | Add all edges. * c | | | * u |Do not recurse. | Recurse. | Recurse. * r | | | * s ---|------------------|-------------------|------------------ * i 2 |Impossible. | Do not add | Add all vertices. * o | | vertices. | * n | | | * L | | Add edges only if | Add all edges. * e | | vertices are | * v | | already included. | * e | | | * l | | Do not recurse. | Do not recurse. | | | | ---|------------------|-------------------|------------------ */ Boolean bNeedToRecurse = GetNeedToRecurse(eNetworkLevel, iRecursionLevel); Boolean bNeedToAppendVertices = GetNeedToAppendVertices( eNetworkLevel, iRecursionLevel); ReportProgress("Getting tags related to \"" + sTag + "\"."); String sUrl = GetFlickrMethodUrl("flickr.tags.getRelated", sApiKey, "&tag=" + UrlUtil.EncodeUrlParameter(sTag)); XmlDocument oXmlDocument; try { oXmlDocument = GetXmlDocument(sUrl, oRequestStatistics); } catch (Exception oException) { // If the exception is not a WebException or XmlException, or if // none of the network has been obtained yet, throw the exception. if (!HttpSocialNetworkUtil.ExceptionIsWebOrXml(oException) || !oGraphMLXmlDocument.HasVertexXmlNode) { throw oException; } return; } // The document consists of a single "tags" node with zero or more // "tag" child nodes. String sOtherTag = null; XmlNodeList oTagNodes = oXmlDocument.DocumentElement.SelectNodes( "tags/tag"); if (oTagNodes.Count > 0) { AppendVertexXmlNode(sTag, oGraphMLXmlDocument, oTagDictionary); } foreach (XmlNode oTagNode in oTagNodes) { sOtherTag = XmlUtil2.SelectRequiredSingleNodeAsString(oTagNode, "text()", null); if (bNeedToAppendVertices) { AppendVertexXmlNode(sOtherTag, oGraphMLXmlDocument, oTagDictionary); } if (bNeedToAppendVertices || oTagDictionary.ContainsKey(sOtherTag)) { oGraphMLXmlDocument.AppendEdgeXmlNode(sTag, sOtherTag); } } if (bNeedToRecurse) { foreach (XmlNode oTagNode in oTagNodes) { sOtherTag = XmlUtil2.SelectRequiredSingleNodeAsString(oTagNode, "text()", null); GetRelatedTagsRecursive(sOtherTag, eWhatToInclude, eNetworkLevel, sApiKey, 2, oGraphMLXmlDocument, oTagDictionary, oRequestStatistics); } } }
EnumerateXmlNodes ( String sUrl, String sXPath, Int32 iMaximumXmlNodes, Boolean bSkipMostPage1Errors, RequestStatistics oRequestStatistics ) { Debug.Assert( !String.IsNullOrEmpty(sUrl) ); Debug.Assert( !String.IsNullOrEmpty(sXPath) ); Debug.Assert(iMaximumXmlNodes > 0); Debug.Assert(oRequestStatistics != null); AssertValid(); Int32 iStartIndex = 1; Int32 iMaxResults = 50; Int32 iXmlNodesEnumerated = 0; while (true) { if (iStartIndex > 1) { ReportProgress("Getting page starting with item " + iStartIndex + "."); } String sUrlWithPagination = String.Format( "{0}{1}start-index={2}&max-results={3}" , sUrl, sUrl.IndexOf('?') == -1 ? '?' : '&', iStartIndex, iMaxResults ); XmlDocument oXmlDocument; XmlNamespaceManager oXmlNamespaceManager; try { oXmlDocument = GetXmlDocument(sUrlWithPagination, oRequestStatistics, out oXmlNamespaceManager); } catch (Exception oException) { if (!HttpSocialNetworkUtil.ExceptionIsWebOrXml(oException)) { throw oException; } if (iStartIndex > 1 || bSkipMostPage1Errors) { // Always skip errors on page 2 and above. yield break; } throw (oException); } XmlNodeList oXmlNodesThisPage = oXmlDocument.SelectNodes(sXPath, oXmlNamespaceManager); Int32 iXmlNodesThisPage = oXmlNodesThisPage.Count; if (iXmlNodesThisPage == 0) { yield break; } for (Int32 i = 0; i < iXmlNodesThisPage; i++) { yield return ( oXmlNodesThisPage[i] ); iXmlNodesEnumerated++; if (iXmlNodesEnumerated == iMaximumXmlNodes) { yield break; } } // The next page, if there is one, is obtained from a link tag that // looks something like this: // // <link rel="next" ... href="http://gdata.youtube.com/feeds/...? // start-index=26&max-results=25"/> String sHRef; if ( !XmlUtil2.TrySelectSingleNodeAsString(oXmlDocument, "a:feed/a:link[@rel='next']/@href", oXmlNamespaceManager, out sHRef) ) { yield break; } const String Pattern = @"start-index=(?<NextStartIndex>\d+)"; Regex oRegex = new Regex(Pattern); Match oMatch = oRegex.Match(sHRef); if (!oMatch.Success || !MathUtil.TryParseCultureInvariantInt32( oMatch.Groups["NextStartIndex"].Value, out iStartIndex) ) { yield break; } // Get the next page... } }
EnumerateXmlNodes ( String sUrl, String sXPath, Int32 iMaximumXmlNodes, Boolean bSkipMostPage1Errors, RequestStatistics oRequestStatistics ) { Debug.Assert(!String.IsNullOrEmpty(sUrl)); Debug.Assert(!String.IsNullOrEmpty(sXPath)); Debug.Assert(iMaximumXmlNodes > 0); Debug.Assert(oRequestStatistics != null); AssertValid(); // A maximum per-page value of 500 works for // flickr.contacts.getPublicList (maximum per_page = 1000) and // flickr.people.getPublicPhotos (maximum per_page = 500). Debug.Assert(sUrl.IndexOf("flickr.contacts.getPublicList") >= 0 || sUrl.IndexOf("flickr.people.getPublicPhotos") >= 0); Int32 iMaximumPerPage = Math.Min(500, iMaximumXmlNodes); Int32 iPage = 1; Int32 iXmlNodesEnumerated = 0; while (true) { String sUrlWithPagination = String.Format( "{0}{1}per_page={2}&page={3}" , sUrl, sUrl.IndexOf('?') == -1 ? '?' : '&', iMaximumPerPage, iPage ); XmlDocument oXmlDocument; try { oXmlDocument = GetXmlDocument(sUrlWithPagination, oRequestStatistics); } catch (Exception oException) { if (!HttpSocialNetworkUtil.ExceptionIsWebOrXml(oException)) { throw oException; } if (iPage > 1 || bSkipMostPage1Errors) { // Always skip errors on page 2 and above. yield break; } throw (oException); } XmlNodeList oXmlNodesThisPage = oXmlDocument.SelectNodes(sXPath, null); Int32 iXmlNodesThisPage = oXmlNodesThisPage.Count; if (iXmlNodesThisPage == 0) { yield break; } for (Int32 i = 0; i < iXmlNodesThisPage; i++) { yield return(oXmlNodesThisPage[i]); iXmlNodesEnumerated++; if (iXmlNodesEnumerated == iMaximumXmlNodes) { yield break; } } iPage++; // Get the next page... } }