using Examine; using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Xml.Linq; namespace Umbraco.Cms.Tests.Integration.Umbraco.Examine.Lucene.UmbracoExamine { /// /// LEGACY!! Static methods to help query umbraco xml /// /// /// This should be deleted when we remove the old xml published content with tests which should be replaced with nucache tests /// internal static class ExamineExtensions { /// /// Returns true if the XElement is recognized as an umbraco xml NODE (doc type) /// /// /// internal static bool IsExamineElement(this XElement x) { var id = (string)x.Attribute("id"); if (string.IsNullOrEmpty(id)) return false; int parsedId; if (int.TryParse(id, out parsedId)) if (parsedId > 0) return true; return false; } /// /// This takes into account both schemas and returns the node type alias. /// If this isn't recognized as an element node, this returns an empty string /// /// /// internal static string ExamineNodeTypeAlias(this XElement x) { return string.IsNullOrEmpty((string)x.Attribute("nodeTypeAlias")) ? x.Name.LocalName : (string)x.Attribute("nodeTypeAlias"); } /// /// Returns umbraco value for a data element with the specified alias. /// /// /// /// internal static string SelectExamineDataValue(this XElement xml, string alias) { XElement nodeData = null; //if there is data children with attributes, we're on the old if (xml.Elements("data").Any(x => x.HasAttributes)) nodeData = xml.Elements("data").SingleOrDefault(x => string.Equals((string)x.Attribute("alias"), alias, StringComparison.InvariantCultureIgnoreCase)); else nodeData = xml.Elements().FirstOrDefault(x => string.Equals(x.Name.ToString(), alias, StringComparison.InvariantCultureIgnoreCase)); if (nodeData == null) return string.Empty; if (!nodeData.HasElements) return nodeData.Value; //it has sub elements so serialize them var reader = nodeData.CreateReader(); reader.MoveToContent(); return reader.ReadInnerXml(); } [EditorBrowsable(EditorBrowsableState.Never)] public static ValueSet ConvertToValueSet(this XElement xml, string indexCategory) { if (!xml.IsExamineElement()) throw new InvalidOperationException("Not a supported Examine XML structure"); var allVals = xml.SelectExamineAllValues(); var id = (string)xml.Attribute("id"); //we will use this as the item type, but we also need to add this as the 'nodeTypeAlias' as part of the properties //since this is what Umbraco expects var nodeTypeAlias = xml.ExamineNodeTypeAlias(); var set = new ValueSet(id, indexCategory, nodeTypeAlias, allVals); set.Set("nodeTypeAlias", nodeTypeAlias); return set; } internal static Dictionary SelectExamineAllValues(this XElement xml) { var attributeValues = xml.Attributes().ToDictionary(x => x.Name.LocalName, x => x.Value); var dataValues = xml.SelectExamineDataValues(); foreach (var v in attributeValues) //override the data values with attribute values if they do match, otherwise add dataValues[v.Key] = v.Value; return dataValues; } internal static Dictionary SelectExamineDataValues(this XElement xml) { //resolve all element data at once since it is much faster to do this than to relookup all of the XML data //using Linq and the node.Elements() methods re-gets all of them. var elementValues = new Dictionary(); foreach (var x in xml.Elements()) { if (x.Attribute("id") != null) continue; string key; if (x.Name.LocalName == "data") //it's the legacy schema key = (string)x.Attribute("alias"); else key = x.Name.LocalName; if (string.IsNullOrEmpty(key)) continue; if (!x.HasElements) elementValues[key] = x.Value; else //it has sub elements so serialize them using (var reader = x.CreateReader()) { reader.MoveToContent(); elementValues[key] = reader.ReadInnerXml(); } } return elementValues; } } }