The MTPS Content Service requires no registration nor authentication.
The MTPS Content Service is a read-only service; no facilities are provided for updating or amending content.
Use of the MTPS Content Services is governed by the Microsoft Terms of Use.
The formal service description (WSDL) can be found here.
| Format | Description |
|---|---|
| Mtps.Xhtml | XHTML-compliant, presentation-free page. |
| Mtps.Toc | Fragment of the table-of-contents site navigation. One single fragment contains one root element and a set of children one level deep. Using a hierarchical TreeView representation for reference, there exists a fragment for each level on each branch of the TOC. |
| Format | Description |
|---|---|
| Mtps.Links | Provides a mapping between source-specific ‘asset IDs’ and MTPS-specific content identifiers. |
| Mtps.Search | Metadata tags typically used for search indexing. |
The MTPS Content Service currently supports two operations: GetContent and GetNavigationPaths.
The GetContent operation allows a caller to request a particular content item from the content store, or to find a list of potential alternates if an unambiguous content key is not known.
The formal definition of the request can be found in the WSDL (available here ). Here is an sample of what a request might look like:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<getContentRequest xmlns="urn:msdn-com:public-content-syndication">
<contentIdentifier>ms224917</contentIdentifier>
<locale xmlns="urn:mtpg-com:mtps/2004/1/key">en-us</locale>
<version xmlns="urn:mtpg-com:mtps/2004/1/key">VS.80</version>
<requestedDocuments>
<requestedDocument type="Common" selector="Mtps.Search" />
<requestedDocument type="Primary" selector="Mtps.Xhtml" />
</requestedDocuments>
</getContentRequest>
</soap:Body>
</soap:Envelope>
Here, a SOAP 1.1 request is shown, but a SOAP 1.2 binding is also supported.
The request consists of a three-part content key - a content identifier (which can be either a content short ID, a content GUID, a content alias, or a content URL, or an asset ID) , a locale, and a version - and zero or more requested document descriptors .
Version is optional. If version is not specified, the latest version is assumed. Locale, however, is required. Failure to specify locale will result in a partial match.
Note that if the request contains a content URL and the URL contains version and/or locale information, and the request also contains version and/or locale information, then the version/locale in the request itself override the version/locale in the URL.
Several response scenarios are possible:
When the provided content identifier - short ID, GUID, or alias - is found in the database, and when a content item exactly matching the requested version and locale exists, an exact match has occurred. In this case, several things are returned with the response:
Given the sample request shown above, a response for an exact match might look as follows:
<soap:Envelope
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<getContentResponse
xmlns="urn:msdn-com:public-content-syndication"
xmlns:k="urn:mtpg-com:mtps/2004/1/key">
<k:contentId>ms224917</k:contentId>
<k:contentGuid>10447dd7-07a1-4856-b00e-6f31465ac63f</k:contentGuid>
<k:contentAlias />
<k:locale>en-us</k:locale>
<k:version>VS.80</k:version>
<availableVersionsAndLocales>
<availableVersionAndLocale>
<k:locale>en-us</k:locale>
<k:version>VS.80</k:version>
</availableVersionAndLocale>
<availableVersionAndLocale>
<k:locale>en-us</k:locale>
<k:version>VS.90</k:version>
</availableVersionAndLocale>
</availableVersionsAndLocales>
<primaryDocuments>
<p:primary primaryCat:primaryFormat="Mtps.Xhtml"
xmlns:primaryCat="urn:mtpg-com:mtps/2004/1/primary/category"
xmlns:p="urn:mtpg-com:mtps/2004/1/primary">
<xhtml:xhtml>
<!-- Content omitted for clarity -->
</xhtml:xhtml>
</p:primary>
</primaryDocuments>
<imageDocuments />
<commonDocuments>
<c:common commonCat:commonFormat="MTPS.Links"
xmlns:commonCat="urn:mtpg-com:mtps/2004/1/common/category"
xmlns:c="urn:mtpg-com:mtps/2004/1/common" />
<c:common commonCat:commonFormat="MTPS.Search"
xmlns:commonCat="urn:mtpg-com:mtps/2004/1/common/category"
xmlns:c="urn:mtpg-com:mtps/2004/1/common">
<search>
<!-- Content omitted for clarity -->
</search>
</c:common>
</commonDocuments>
<featureDocuments />
</getContentResponse>
</soap:Body>
</soap:Envelope>
Again, this sample shows the SOAP 1.1 version, but SOAP 1.2 responses would be generated in response to a SOAP 1.2 request.
There are several things to note about this response:
If the content key provided in the request identifies an existing content item, but the specified version and locale are not present (or version is not specified and the specified locale is not present), there is a partial match. In this case, only two things are returned:
If the sample request above were only a partial match, the response might look as follows:
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<getContentResponse xmlns="urn:msdn-com:public-content-syndication"
xmlns:k="urn:mtpg-com:mtps/2004/1/key">
<k:contentId>ms224917</k:contentId>
<k:contentGuid>10447dd7-07a1-4856-b00e-6f31465ac63f</k:contentGuid>
<k:contentAlias />
<k:locale />
<k:version />
<availableVersionsAndLocales>
<availableVersionAndLocale>
<k:locale>en-us</k:locale>
<k:version>VS.90</k:version>
</availableVersionAndLocale>
<availableVersionAndLocale>
<k:locale>de-de</k:locale>
<k:version>test.20</k:version>
</availableVersionAndLocale>
</availableVersionsAndLocales>
<primaryDocuments />
<imageDocuments />
<commonDocuments />
<featureDocuments />
</getContentResponse>
</soap:Body>
</soap:Envelope>
Note that no documents are returned - basically just the various content identifiers and the available versions and locales. Generally the correct action in response to a partial match will be to select one of the available versions and locales, and then to retry the request. That should result in an exact match.
If the content key in the request does not match any content item in the database, a fault is returned.
When a problem occurs, a SOAP fault of the appropriate version (1.1 or 1.2) is returned.
The faultstring (SOAP 1.1) or Reason/Text (SOAP 1.2) element
of the fault will contain a human-readable, English message describing the error
which has occurred. The detail element of the fault will contain MTPS-specific
information about the error, in the form of a mtps:mtpsFaultDetail
element. The formal schema for that element can be found in the
WSDL document. Here is a brief description of each of the elements:
| Element | Description |
|---|---|
| eventId | A code describing the error. See table below. |
| source | The source of the error. Always "GetContent". |
| helpLink | The URL of a webpage containing helpful information about the error and how to resolve it. |
The error codes in the eventId element will be one of the following:
| Code | Description |
|---|---|
| mtpsContentIdentifierNotFound | The specified content identifier did not correspond to any content items in MTPS. |
| mtpsContentIdentifierAbsent | There was no content identifier in the request. |
| mtpsContentIdentifierInvalidFormat | The content identifier in the request was in an incorrect format. |
| mtpsRequestAbsent |
The soap:Body element did not contain a request of the appropriate type.
|
| mtpsVersionInvalidFormat | The version in the request was in an incorrect format. |
| mtpsLocaleNull | The locale was not specified in the request. |
| mtpsLocaleInvalidFormat | The locale in the request was in an incorrect format. |
| mtpsGeneralServerError | Some other error occurred. |
The below samples demonstrate the use of the MTPS Content Service. They assume that a proxy has been generated via "Add Web Reference" in Visual Studio 2005, and that using statements have brought in the namespaces System, System.Web.Services.Protocols, System.Xml, System.Xml.Serialization, and whatever namespace you assigned to your proxy when running "Add Web Reference".
// Create the request object
getContentRequest request = new getContentRequest();
// Assign the short ID, version, and locale
request.contentIdentifier = "abhtw0f1"; // System.Xml.XmlReader.Read
request.locale = "en-us";
request.version = "VS.80";
// Create the proxy and set the SOAP version
ContentService proxy = new ContentService();
proxy.SoapVersion = SoapProtocolVersion.Soap11;
// Call the web service
getContentResponse response = proxy.GetContent(request);
Console.WriteLine(response.contentId); // abhtw0f1
Console.WriteLine(response.locale); // en-us
Console.WriteLine(response.version); // VS.80
// Two common documents are returned
Console.WriteLine(response.commonDocuments.Length); // 2
// The first common document contains search info
Console.WriteLine(response.commonDocuments[0].commonFormat); // MTPS.Search
// No contents were requested, so we only get summary info like format
Console.WriteLine(response.commonDocuments[0].Any.Length); // 0
// One other version/locale is available (German)
// The first version/locale is the one we passed in
Console.WriteLine(response.availableVersionsAndLocales.Length); // 2
Console.WriteLine(response.availableVersionsAndLocales[0].locale); // en-us
Console.WriteLine(response.availableVersionsAndLocales[0].version); // VS.80
Console.WriteLine(response.availableVersionsAndLocales[1].locale); // de-de
Console.WriteLine(response.availableVersionsAndLocales[1].version); // VS.80
// Create the request object
getContentRequest request = new getContentRequest();
// Assign the GUID, version, and locale
request.contentIdentifier = "4de07e43-5601-446e-9105-1144a5fdb08d";
request.locale = "en-us";
request.version = "VS.80";
// Specify that we want the XHTML primary document contents to come back
requestedDocument[] documents = new requestedDocument[1];
documents[0] = new requestedDocument();
documents[0].type = documentTypes.primary;
documents[0].selector = "Mtps.Xhtml";
request.requestedDocuments = documents;
// Create the proxy. No need to set version since SOAP 1.2 is the default
ContentService proxy = new ContentService();
// Call the web service
getContentResponse response = proxy.GetContent(request);
Console.WriteLine(response.contentId); // abhtw0f1
Console.WriteLine(response.contentGuid); // 4de07e43-5601-446e-9105-1144a5fdb08d
Console.WriteLine(response.locale); // en-us
Console.WriteLine(response.version); // VS.80
// Two primary documents are returned
Console.WriteLine(response.primaryDocuments.Length); // 2
// The first primary document contains the XHTML
Console.WriteLine(response.primaryDocuments[0].primaryFormat); // Mtps.Xhtml
// Contents were requested, so we get the Xhtml
Console.WriteLine(response.primaryDocuments[0].Any.Name); // div
// Create the request object
getContentRequest request = new getContentRequest();
// Assign the GUID, version, and locale
request.contentIdentifier = "ms288592";
request.locale = "en-us";
request.version = "VS.80";
// Specify that we want the Mtps.Toc and Mtps.Xhtml primary document contents to come back
requestedDocument[] documents = new requestedDocument[2];
documents[0] = new requestedDocument();
documents[0].type = documentTypes.primary;
documents[0].selector = "Mtps.Xhtml";
documents[1] = new requestedDocument();
documents[1].type = documentTypes.primary;
documents[1].selector = "Mtps.Toc";
request.requestedDocuments = documents;
// Create the proxy. No need to set version since SOAP 1.2 is the default
ContentService proxy = new ContentService();
// Call the web service
getContentResponse response = proxy.GetContent(request);
Console.WriteLine(response.contentId); // abhtw0f1
Console.WriteLine(response.contentGuid); // 4de07e43-5601-446e-9105-1144a5fdb08d
Console.WriteLine(response.locale); // en-us
Console.WriteLine(response.version); // VS.80
// Two primary documents are returned
Console.WriteLine(response.primaryDocuments.Length); // 2
// Order is not guaranteed, so the first document might be either
// the Mtps.Toc or the Mtps.Xhtml document. Loop until we find the
// one we want
foreach (primary primaryDoc in response.primaryDocuments)
{
Console.WriteLine(primaryDoc.primaryFormat); // Mtps.Xhtml or Mtps.Toc
Console.WriteLine(response.primaryDocuments[0].Any.Name); // <div> or <toc>
}
// Create the request object
getContentRequest request = new getContentRequest();
// Assign the GUID, version, and locale
request.contentIdentifier = "4de07e43-5601-446e-9105-1144a5fdb08d";
request.locale = "en-us";
request.version = "VS.80";
// Create the proxy. No need to set version since SOAP 1.2 is the default
ContentService proxy = new ContentService();
// Call the web service
getContentResponse response = proxy.GetContent(request);
Console.WriteLine(response.contentId); // abhtw0f1
Console.WriteLine(response.contentGuid); // 4de07e43-5601-446e-9105-1144a5fdb08d
// Console.WriteLine(response.locale); // null when no exact match
// Console.WriteLine(response.version); // null when no exact match
// Nine other versions/locales available
Console.WriteLine(response.availableVersionsAndLocales.Length); // 9
Console.WriteLine(response.availableVersionsAndLocales[0].locale); // de-de - German
Console.WriteLine(response.availableVersionsAndLocales[0].version); // VS.80
// Create the request object
getContentRequest request = new getContentRequest();
// Assign the alias, version, and locale
request.contentIdentifier = "System.Xml.XmlWroter"; // misspelling
request.locale = "en-us";
request.version = "VS.80";
// Create the proxy. No need to set version since SOAP 1.2 is the default
ContentService proxy = new ContentService();
// Call the web service
try
{
getContentResponse response = proxy.GetContent(request);
}
catch (SoapException e)
{
XmlNode detail = e.Detail;
XmlNamespaceManager nsmgr =
new XmlNamespaceManager(detail.OwnerDocument.NameTable);
nsmgr.AddNamespace("mtps", "urn:msdn-com:public-content-syndication");
// Print the eventID, helpLink, and source
Console.WriteLine(detail.SelectSingleNode("mtps:mtpsFaultDetail/mtps:eventId/text()").Value);
Console.WriteLine(detail.SelectSingleNode("mtps:mtpsFaultDetail/mtps:helpLink/text()").Value);
Console.WriteLine(detail.SelectSingleNode("mtps:mtpsFaultDetail/mtps:source/text()").Value);
}
// Create the request object
getContentRequest request = new getContentRequest();
// Assign the URL, version, and locale
// Note that the URL specifies a version and a locale
request.contentIdentifier = "http://msdn2.microsoft.com/eak978d4(de-de,VS.70).aspx";
request.locale = null;
request.version = "VS.80";
// Create the proxy and set the SOAP version
ContentService proxy = new ContentService();
proxy.SoapVersion = SoapProtocolVersion.Soap11;
// Call the web service
getContentResponse response = proxy.GetContent(request);
Console.WriteLine(response.contentId); // eak978d4
// Note that the request.version overrides the version embedded in the URL
Console.WriteLine(response.version); // VS.80
// But because request.locale was null, the locale from the URL is used
Console.WriteLine(response.locale); // de-de
// Two common documents are returned
Console.WriteLine(response.commonDocuments.Length); // 2
// The first common document contains search info
Console.WriteLine(response.commonDocuments[0].commonFormat); // MTPS.Search
// No contents were requested, so we only get summary info like format
Console.WriteLine(response.commonDocuments[0].Any.Length); // 0
// One other version/locale is available (German)
// The first version/locale is the one we passed in
Console.WriteLine(response.availableVersionsAndLocales.Length); // 2
Console.WriteLine(response.availableVersionsAndLocales[0].locale); // en-us
Console.WriteLine(response.availableVersionsAndLocales[0].version); // VS.80
Console.WriteLine(response.availableVersionsAndLocales[1].locale); // de-de
Console.WriteLine(response.availableVersionsAndLocales[1].version); // VS.80
Navigation path data - sometimes referred to as Table of Contents (TOC) information despite the fact that it is more broadly useful than simply providing a TOC - is somewhat non-intuitive in structure. Navigation path data for a content item is not stored within the content item itself. Rather, there is an entirely separate hierarchy of content items that describe the navigational struture. These content items are easily distinguished by the presence of an Mtps.Toc document. Mtps.Toc documents contain a description of a content item and its immediate children, as well as content keys for the Mtps.Toc documents of those children. Using this information, it is possible to traverse the entire navigation structure, but it would be highly inefficient.
The GetNavigationPaths operation allows a client to request all the possible navigational routes between two topics in a single round trip. Note that more than one route may exist between two topics, as the TOC may list the same topic in multiple places.
The formal definition of the request can be found in the WSDL (available here). Here is an sample of what a request might look like:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<getNavigationPathsRequest xmlns="urn:msdn-com:public-content-syndication">
<root xmlns:k="urn:mtpg-com:mtps/2004/1/key">
<k:contentId>ms224917</k:contentId>
<k:locale>en-us</k:locale>
<k:version>SQL.90</k:version>
</root>
<target xmlns:k="urn:mtpg-com:mtps/2004/1/key">
<k:contentId>ms259124</k:contentId>
<k:locale>en-us</k:locale>
<k:version>SQL.90</k:version>
</target>
</getNavigationPathsRequest>
</soap:Body>
</soap:Envelope>
Here, a SOAP 1.1 request is shown, but a SOAP 1.2 binding is also supported.
The request consists of two parts: a root and a target. Each of these consists of a content short identifier, a locale, and a version - collectively a navigation key. All three parts are required, and content identifiers other than a short identifier (e.g. a content GUID or content alias) are not currently supported.
The root identifies the content item that is the start of the requested navigation paths. The target identifies the content item that is the endpoint of the requested navigation paths. Root should be a navigational-type item. Target should be a content-type item, not a navigational-type item. That is, root should refer to an item that has a document of type Mtps.Toc, while target should refer to an item that has a document of type Mtps.Xhtml.
The most commonly used root will be the topmost node in the TOC tree. This node has a short ID of ms310241 and a version of MSDN.10.
Here is a sample of what a response might look like:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<getNavigationPathsResponse
xmlns="urn:msdn-com:public-content-syndication"
xmlns:k="urn:mtpg-com:mtps/2004/1/key">
<navigationPaths>
<navigationPath>
<navigationPathNodes>
<navigationPathNode>
<navigationNodeKey>
<k:contentId>ms224917</k:contentId>
<k:locale>en-us</k:locale>
<k:version>SQL.90</k:version>
</navigationNodeKey>
<isPhantom>false</isPhantom>
<contentNodeKey>
<k:contentId>ms224928</k:contentId>
<k:locale>en-us</k:locale>
<k:version>test.10</k:version>
</contentNodeKey>
<title>LVL1_WDRT001_TOPIC01</title>
</navigationPathNode>
<navigationPathNode>
<navigationNodeKey>
<k:contentId>ms224923</k:contentId>
<k:locale>en-us</k:locale>
<k:version>test.20</k:version>
</navigationNodeKey>
<isPhantom>false</isPhantom>
<contentNodeKey>
<k:contentId>ms224923</k:contentId>
<k:locale>en-us</k:locale>
<k:version>test.20</k:version>
</contentNodeKey>
<title>LVL1_WDRT001_TOPIC02</title>
</navigationPathNode>
</navigationPathNodes>
</navigationPath>
<navigationPath>
<navigationPathNodes>
<navigationPathNode>
<navigationNodeKey>
<k:contentId>ms224923</k:contentId>
<k:locale>en-us</k:locale>
<k:version>test.10</k:version>
</navigationNodeKey>
<isPhantom>false</isPhantom>
<contentNodeKey>
<k:contentId>ms224928</k:contentId>
<k:locale>en-us</k:locale>
<k:version>test.10</k:version>
</contentNodeKey>
<title>LVL1_WDRT001_TOPIC01</title>
</navigationPathNode>
<navigationPathNode>
<navigationNodeKey>
<k:contentId>ms224923</k:contentId>
<k:locale>en-us</k:locale>
<k:version>test.10</k:version>
</navigationNodeKey>
<isPhantom>true</isPhantom>
<contentNodeKey>
<k:contentId>ms224939</k:contentId>
<k:locale>en-us</k:locale>
<k:version>test.10</k:version>
</contentNodeKey>
<title>LVL1_WDRT001_SUBTREE_REFERENCE</title>
</navigationPathNode>
<navigationPathNode>
<navigationNodeKey>
<k:contentId>ms224923</k:contentId>
<k:locale>en-us</k:locale>
<k:version>test.20</k:version>
</navigationNodeKey>
<isPhantom>false</isPhantom>
<contentNodeKey>
<k:contentId>ms224923</k:contentId>
<k:locale>en-us</k:locale>
<k:version>test.20</k:version>
</contentNodeKey>
<title>LVL2_WDRT001_TOPIC02</title>
</navigationPathNode>
</navigationPathNodes>
</navigationPath>
</navigationPaths>
</getNavigationPathsResponse>
</soap:Body>
</soap:Envelope>
The reponse is structured as follows:
The distinction between navigationNodeKey and contentNodeKey requires some explanation of the way navigation data is structured in the MTPS system. For each node in the table of contents (TOC), there are actually two content items: one for the TOC node itself, and one for the corresponding content. On the MSDN website, these correspond to the currently selected node in the left-hand navigation tree, and the content that appears in the main area of the window. This degree of separation is necessary because a particular content item could actually appear in two locations in the TOC.
To reflect this structure, two content keys are returned for each navigationPathNode. The navigationNodeKey identifies the TOC item itself. One could, for example, use this key with the GetContent operation to retrieve the Mtps.Toc document that lists all the children of this TOC node. The contentNodeKey, on the other hand, identifies the content item to which this TOC node operates. For example, if the current node is the TOC entry for a class, the contentNodeKey might identify the content item containing the Mtps.Xhtml document with overview information for the class.
Phantom nodes are a byproduct of the way navigational data is structured within MTPS. Essentially, they are "placeholder" navigational nodes that the system must interject. A node is a phantom node if the the <isPhantom> element in a <navigationPathNode> has a value of "true". In almost all cases, the correct way to handle phantoms is to skip them - to process as if the phantom node were not returned at all.
The sample code below demonstrates the correct handling of phantom nodes.
Faults are returned in the same manner as identified for GetContent faults. This table describes possible fault conditions and fault codes for GetNavigationPaths:
| Code | Description |
|---|---|
| mtpsContentIdentifierNotFound | The specified content identifier did not correspond to any content items in MTPS. |
| mtpsRootAbsent |
The root element was missing from the request.
|
| mtpsTargetAbsent |
The target element was missing from the request.
|
| mtpsRequestAbsent |
The soap:Body element did not contain a request of the appropriate type.
|
| mtpsContentIdNull |
The contentId element was missing or empty in either the root
or the target..
|
| mtpsContentIdInvalidFormat |
The contentId element was in an invalid format in either the root
or the target.
|
| mtpsVersionNull |
The version was not specified in either the root
or the target..
|
| mtpsVersionInvalidFormat | The version in the request was in an incorrect format. |
| mtpsLocaleNull |
The locale was not specified in either the root
or the target..
|
| mtpsLocaleInvalidFormat |
The locale in the request was in an incorrect format in either the root
or the target.
|
| mtpsGeneralServerError | Some other error occurred. |
The below samples demonstrate the use of the MTPS Content Service. They assume that a proxy has been generated via "Add Web Reference" in Visual Studio 2005.
ContentService proxy = new ContentService();
navigationKey root = new navigationKey();
// This is the root of the MSDN English TOC tree - you'll
// probably specify this as your root most often.
root.contentId = "ms123401";
root.locale = "en-us";
root.version = "MSDN01.10";
navigationKey target = new navigationKey();
target.contentId = "abhtw0f1";
target.locale = "en-us";
target.version = "VS.80";
getNavigationPathsRequest request = new getNavigationPathsRequest();
request.root = root;
request.target = target;
getNavigationPathsResponse response = proxy.GetNavigationPaths(request);
Console.WriteLine("There were {0} paths between the root and the target.",
response.navigationPaths.Length);
int pathNumber = 1;
// Loop through all the resultant navigation paths
foreach (navigationPath path in response.navigationPaths)
{
Console.WriteLine("Path number {0}", pathNumber++);
int nodeNumber = 1;
int phantoms = 0;
// For each path, loop over all the navigationPathNodes. Skip any
// phantom nodes.
foreach (navigationPathNode node in path.navigationPathNodes)
{
if (node.isPhantom)
{
++phantoms;
}
else
{
// For each node, print out the relevant information
Console.WriteLine("Node number {0}: ", nodeNumber++);
Console.WriteLine("Title: {0}", node.title);
Console.WriteLine("Navigation node: {0}, {1}, {2}",
node.navigationNodeKey.contentId,
node.navigationNodeKey.locale,
node.navigationNodeKey.version);
Console.WriteLine("Content node: {0}, {1}, {2}",
node.contentNodeKey.contentId,
node.contentNodeKey.locale,
node.contentNodeKey.version);
}
}
Console.WriteLine("Skipped {0} phantom nodes.", phantoms);
}
The Mtps.Xhtml primary document is the main document type in MTPS. It holds the XHTML content of a content item. This XHTML is generally compliant with the W3C’s Modular XHTML 1.1 standard. Because of the large amount of legacy content in the system, there are instances where complete compliance was not possible, but content is always well-formed XML. In most cases it is also standards-compliant.
It is important to note that the XHTML MTPS manages is “presentation-free”. That is, the XHTML contains no script, styles, or other artifacts that would control the look and feel of the rendered content. This allows the XHTML to be used in many different contexts by having styling applied at runtime, after the document is retrieved. The Mtps.Xhtml document does, however, contain some extension elements (easily detectible by the fact that they are not in the XHTML namespace) to enable certain behaviors on the MSDN2 website. If processing these extra elements would cause problems for your application, you can always use the Mtps.Failsafe primary document instead. When available, it is an equivalent to the Mtps.Xhtml document that contains only XHTML elements.
Some of the common extension elements used in Mtps.Xhtml documents are listed
in the following table. The "mtps" prefix indicates a namespace URI of
http://msdn2.microsoft.com/mtps.
| Element | Description |
|---|---|
mtps:CodeSnippet |
Contains a chunk of code. This element may have a Language
attribute indicating the language in which the code is written.
Language might also have a value of "None" indicating that
it is in no particular programming language. For instance, an XML
sample common to all code snippets in a document may have a
Language of "None".
|
mtps:CollapsibleArea |
As the name implies, indicates a region of the document intended to be
collapsible. May have a Title attribute containing the title
of the region.
|
mtps:InstrumentedLink |
Represents a hyperlink. The NavigateUrl attribute will contain
a URL (usually an asset ID) that is the target
of the link.
|
mtps:KTableControl |
TODO: I don't think I really understand what this thing is supposed to do. |
mtps:MemberLink |
TODO: I'm not really sure what this is for. |
The Mtps.Failsafe primary document format is meant to serve as an alternative to the richer Mtps.Xhtml. Mtps.Failsafe contains an XHTML document that contains none of the MTPS extensions present in the Mtps.Xhtml format, and as such may be easier for some consumers to work with.
This XHTML is generally compliant with the W3C’s Modular XHTML 1.1 standard. Because of the large amount of legacy content in the system, there are instances where complete compliance was not possible, but content is always well-formed XML. In most cases it is also standards-compliant.
As described above in the documentation for GetNavigationPaths, the Mtps.Toc primary document format is used to express the navigational structure of content items in MTPS. This is an example of an Mtps.Toc document:
<toc:Node toc:Title="XmlReader Class"
toc:SubTree="AssetId:VS%7ccpref19%7c%24%5ccpref.hxt%400%2c0%2c47"
toc:SubTreeVersion="VS.80"
toc:SubTreeLocale="en-US"
toc:Description=""
toc:Target="AssetId:T%3aSystem.Xml.XmlReader"
toc:TargetLocale="en-US"
toc:TargetVersion="VS.80"
toc:IsPhantom="false"
xmlns:toc="urn:mtpg-com:mtps/2004/1/toc">
<toc:Node toc:Title="XmlReader Members"
toc:Target="AssetId:AllMembers.T%3aSystem.Xml.XmlReader"
toc:TargetLocale="en-US"
toc:TargetVersion="VS.80"
toc:IsPhantom="false" />
<toc:Node toc:Title="XmlReader Constructor"
toc:Target="AssetId:M%3aSystem.Xml.XmlReader.%23ctor"
toc:TargetLocale="en-US"
toc:TargetVersion="VS.80"
toc:IsPhantom="false" />
<toc:Node toc:Title="XmlReader Methods"
toc:SubTree="AssetId:VS%7ccpref19%7c%24%5ccpref.hxt%400%2c0%2c47%2c2"
toc:SubTreeVersion="VS.80"
toc:SubTreeLocale="en-US"
toc:Target="AssetId:Methods.T%3aSystem.Xml.XmlReader"
toc:TargetLocale="en-US"
toc:TargetVersion="VS.80"
toc:IsPhantom="false" />
<toc:Node toc:Title="XmlReader Properties"
toc:SubTree="AssetId:VS%7ccpref19%7c%24%5ccpref.hxt%400%2c0%2c47%2c3"
toc:SubTreeVersion="VS.80"
toc:SubTreeLocale="en-US"
toc:Target="AssetId:Properties.T%3aSystem.Xml.XmlReader"
toc:TargetLocale="en-US"
toc:TargetVersion="VS.80"
toc:IsPhantom="false" />
</toc:Node>
The topmost Node element represents the content item of interest. SubTree, SubTreeVersion, and SubTreeLocale combine to form a contentKey for the content item containing this Mtps.Toc document, and as such are usually not very interesting. Target, TargetLocale, and TargetVersion, however combine to form a content key for the content item containing the Mtps.Xhtml document associated with this navigation node.
Each of the subordinate Node elements represents a navigational child of the topmost element. Each of them has Target, TargetLocale, and TargetVersion attributes with the same semantics - they identify the associated content item. SubTree, SubTreeVersion, and SubTreeLocale may or may not be present, depending on whether that node itself has child nodes. If so, these attributes combine to identify a content item with an Mtps.Toc document one level farther "down" the tree.
The semantics of Title are fairly obvious.
The Description attribute is not used and will always be empty.
The IsPhantom attribute indicates whether this node is a navigational phantom. Phantoms are documented above.
The Mtps.Links document is a convenience addition to any content item whose primary document contains links by asset ID. It is a straightforward XML format mapping asset IDs to short IDs, content GUIDs, and content aliases (if extant). This information is useful to applications wishing to normalize to on identifier form, or for applications wishing to translate from asset IDs to short IDs for use in calls to GetNavigationPaths.
Here is an example of an Mtps.Links document:
<mtps:links xmlns:mtps="urn:msdn-com:public-content-syndication">
<mtps:link>
<mtps:assetid>assetid:t%3asystem.xml.xmlurlresolver</mtps:assetid>
<?xml namespace="" prefix="k" ?>
<k:contentid xmlns:k="urn:mtpg-com:mtps/2004/1/key">008et5fc</k:contentid>
<k:contentguid xmlns:k="urn:mtpg-com:mtps/2004/1/key">725ceabb-b81d-4b7e-8e5c-4b3179bdae5d</k:contentguid>
<k:contentalias xmlns:k="urn:mtpg-com:mtps/2004/1/key">system.xml.xmlurlresolver</k:contentalias>
</mtps:link>
<mtps:link>
<mtps:assetid>assetid:e695047f-3c0f-4045-8708-5baea91cc380</mtps:assetid>
<k:contentid xmlns:k="urn:mtpg-com:mtps/2004/1/key">2bcctyt8</k:contentid>
<k:contentguid xmlns:k="urn:mtpg-com:mtps/2004/1/key">e695047f-3c0f-4045-8708-5baea91cc380</k:contentguid>
<k:contentalias xmlns:k="urn:mtpg-com:mtps/2004/1/key">
</k:contentalias>
</mtps:link>
</mtps:links>