我正在尝试从 XML 获取 XPath,以便我可以使用 XSLT 从 XML 检索数据。我的问题是我看不到 XML,我需要它在 XSLT 中提供 XPath。我怎么知道哪个 XSLT 正在使用哪个 XML。我正在研究 Commerce Server 2009 的搜索 Web 部件。
2 回答
采顿,
我感觉到你的痛苦。首先,让我帮助您更好地了解您正在使用的 SharePoint 可扩展性工具包的体系结构。在可扩展性工具包中,您可能已经看到,有 2 个主要项目控制搜索的执行以及结果的转换和呈现。
控制器层
如果您打开 Microsoft.Commerce.sln 解决方案,请导航到 Portal > Common > Controllers 文件夹。在这里,您将看到包含针对 Commerce Server Foundation 创建和执行 CRUD 操作(CommerceQuery、CommerceUpdate、CommerceDelete 和 CommerceCreate)的代码的所有控制器。
在 SearchController.cs 中,您将看到一个名为 DoProductQuerySearch 的方法。此方法负责通过 Commerce Foundation 执行产品查询。有关我正在谈论的示例,请参见下面的代码片段:
/// <summary>
/// Performs a product query search.
/// </summary>
/// <param name="catalogName">The catalogName</param>
/// <param name="categoryName">The categoryName</param>
/// <param name="requiredProperties">The required product properties</param>
/// <param name="searchPhrase">The search phrase</param>
/// <param name="whereClause">The where clause</param>
/// <param name="orderKey">The property by which the search results should be sorted.</param>
/// <param name="sortOrder">The direction by which the search results should be sorted.</param>
/// <param name="recordIndex">The index of the first result to return</param>
/// <param name="recordsPerPage">The number of records to return.</param>
/// <param name="totalResultCount">An out parameter for the totalResultCount. That is, the total number of hits for the search.</param>
/// <returns>A list of Products.</returns>
public static List<Product> DoProductQuerySearch(string catalogName, string categoryName, List<string> requiredProperties, string searchPhrase, string whereClause, string orderKey, Microsoft.Commerce.Contracts.Messages.SortDirection sortOrder, int recordIndex, int recordsPerPage, out int totalResultCount)
{
List<Product> products = new List<Product>();
var query = new CommerceQuery<CatalogEntity, CommerceCatalogFullTextSearchBuilder>();
query.SearchCriteria.Catalogs.Add(catalogName);
query.SearchCriteria.FirstItemIndex = recordIndex;
query.SearchCriteria.FullTextSearchType = CommerceFullTextSearchType.FreeText;
query.SearchCriteria.NumberOfItemsToReturn = recordsPerPage;
query.SearchCriteria.ReturnTotalItemCount = true;
演示者层
SearchController.DoProductQuerySearch 由 Search Results Presenter 类调用。要查找此类,请导航到 Portal > UI > Search 文件夹并打开 SearchResultsPresenter 类。在 SearchResultsPresenter.cs 类中有一个 GetProductQuerySearchResults 方法,该方法调用以返回 Commerce Entities 列表。在这种方法中,您将看到类似于以下代码的内容:
Collection<Product> products = new Collection<Product>(productResults);
// Set the products in the View
this.View.Products = products;
**ProductXml productXml = new ProductXml(this.GetPropertyCollection(this.View.SearchRequiredProperties), products);**
XsltArgumentList xsltArgList = new XsltArgumentList();
xsltArgList.AddParam("DefaultImagesRepository", string.Empty, SiteContext.Current.DefaultImagesRepository);
xsltArgList.AddParam("_catalog", string.Empty, SiteContext.Current.DefaultCatalogName);
xsltArgList.AddParam("secondSearch", string.Empty, secondSearch);
xsltArgList.AddParam("_currentDate", string.Empty, DateTime.Now.ToString("M/d/yyyy h:mm:ss tt", CultureInfo.CurrentCulture));
xsltArgList.AddParam("_OnlineSearch", string.Empty, this.onlineSearch);
this.RenderResults(xsltArgList, productXml.ToString());
ProductXml 类包含您要查找的内容。导航到 Portal > UI > Catalog >Business 文件夹并双击 ProductXml.cs。在这里,您将看到此类是产品对象的 XML 表示。它包含一组渲染 XML 各个部分的辅助方法。它使用 StringBuilder.Append 手动构建 XML 文档并将其返回给 SearchResultsPresenter 进行显示。在下面的示例中,您可以看到对于搜索结果中的每个产品,OutputProducts 辅助方法调用另一个辅助方法来手动构建构成 XML 文档的 XML 元素。
private string OutputProducts()
{
StringBuilder xmlSb = new StringBuilder(this._products.Count * 512);
xmlSb.Append(XmlElementStartOpen); // <
xmlSb.Append(XmlRootNodeName);
xmlSb.Append(XmlElementStartClose); // >
foreach (Product item in this._products)
{
this.OutputCatalogItem(xmlSb, item);
}
xmlSb.Append(XmlElementEndOpen); // </
xmlSb.Append(XmlRootNodeName);
xmlSb.Append(XmlElementEndClose); // >
return xmlSb.ToString();
}
private void OutputCatalogItem(StringBuilder xmlSb, ICommerceEntity catalogItem, string xmlNodeName)
{
System.Diagnostics.Debug.Assert(xmlSb != null, "The value of xmlSb should never be null.");
xmlSb.Append(XmlElementStartOpen); // <
xmlSb.Append(xmlNodeName);
xmlSb.Append(" ");
xmlSb.Append(Product.PropertyName.Id);
xmlSb.Append(XmlAttributeEqualAndQuote); // ='
xmlSb.Append(catalogItem.Properties[Product.PropertyName.Id]);
xmlSb.Append(XmlAttributeQuote); // '
xmlSb.Append(XmlElementEndClose); // >
this.OutputProperties(xmlSb, catalogItem, this._productProperties);
this.OutputRelatedCatalogItems(xmlSb, catalogItem, HierarchicalCatalogEntity.RelationshipName.CrossSells, XmlCrossSellsNodeName);
this.OutputRelatedCatalogItems(xmlSb, catalogItem, HierarchicalCatalogEntity.RelationshipName.UpSells, XmlUpSellsNodeName);
this.OutputRelatedCatalogItems(xmlSb, catalogItem, HierarchicalCatalogEntity.RelationshipName.KitContents, XmlKitContentsNodeName);
this.OutputCategoryProducts(xmlSb, XmlCategoryProductsNodeName);
this.OutputRelatedCatalogItems(xmlSb, catalogItem, Product.RelationshipName.Variants, XmlVariantsNodeName);
this.OutputPersonalNotes(xmlSb);
xmlSb.Append(XmlElementEndOpen); // </
xmlSb.Append(xmlNodeName);
xmlSb.Append(XmlElementEndClose); // >
xmlSb.ToString();
}
因此,如您所见,没有一个简单的模式可以帮助您编写 xpath 查询,因为 XML 是由 ProductXml 类手动构建的。您有两个选项可以让您更轻松地在 webpart 的关联 XSLT 模板中编写 xpath。
选项 1:(错误选项)手动解析 ProductXML 文件
此选项要求您通读整个 ProductXML 文件,以了解它为给定的一组搜索结果发出的元素和属性结构。
选项 2:(更好的选项)使用 Visual Studio 调试器制作示例 XML 文件
如果您想创建一个 XML 示例文件来帮助您编写 XPATH,您需要在以下代码的 SearchResultsPresenter.GetProductQuerySearchResults 方法的以下行中放置一个断点:
**this.RenderResults(xsltArgList, productXml.ToString());**
调试 w3wp.exe 工作进程,当您遇到此断点时,将 productXml.ToString() 添加到监视窗口并更改 Visual Studio 中的查看器以允许您在监视窗口中以 XML 格式查看输出。然后将xml复制到记事本。这将允许您在对 XSLT 模板中的更改进行编程时从示例 XML 输出开始工作,以便您的 XPath 正确地遍历 DOM。
对“CANBEDOWNLOADED 属性未返回”的更新响应
搜索 Web 部件检索的搜索属性由产品属性选择器控制,该选择器通过导航到 SharePoint 网站的专用网站 Intranet 版本并从 Web 部件属性菜单中选择“修改共享 Web 部件”来找到。在那里,您将找到一个区域来指定应在产品查询中返回哪些属性。当 SearchController 执行 DoProductQuerySearch 时,将活动属性更改为有效地返回会更改从 Commerce Foundation 为 Product Commece 实体请求的属性。您的 XSLT 可能会失败,因为要返回集合的属性不包含 CanBeDowloaded 属性,因为 Web 部件没有将其传递回控制器。我会在 SearchController 中放置一个断点。
var query = new CommerceQuery<CatalogEntity, CommerceCatalogFullTextSearchBuilder>();
然后,将 query.Model.Properties 添加到调试器中的监视窗口,并查看您在 XPATH 语句中查找的属性是否实际上被设置为返回。如果您让该属性在另一个 Web 部件中返回,那么这意味着您在 MetaDataDefinitions.xml 文件中对该属性的配置是正确的,所以这不是罪魁祸首。您的 Web 部件未正确配置为在产品查询中请求 CanBeDownloaded 属性可能很简单。
您可以在 Web 部件属性中更改它。上面的帖子有。如果您使用的是默认的可扩展性工具包,您应该可以使用产品选择器简单地添加它。