07 March 2011

How to retrieve Xml node xPath with c#


 public static string GetXPath(this XmlNode node)
        {
            if (node.NodeType == XmlNodeType.Attribute)
            {
                // attributes have an OwnerElement, not a ParentNode; also they have
                // to be matched by name, not found by position
                return String.Format(
                    "{0}/@{1}",
                    GetXPath(((XmlAttribute)node).OwnerElement),
                    node.Name
                    );
            }

            if (node.ParentNode == null)
            {
                // the only node with no parent is the root node, which has no path
                return "";
            }

            //get the index of the node
            int iIndex = 1;
            XmlNode xnIndex = node;

            while (xnIndex.PreviousSibling != null)
            {
                iIndex++;
                xnIndex = xnIndex.PreviousSibling;
            }

            // the path to a node is the path to its parent, plus "/node()[n]", where
            // n is its position among its siblings.
            return String.Format(
                "{0}/{1}[{2}]",
                GetXPath(node.ParentNode),
                node.Name,
                iIndex
                );
        }
Place holder in c# .net - Parser

look on it,

Lets define a place holder as follow :  identified string with some meaning.

Identification :

          {placeHolder:property}

e.g.

          Data Source={connection_string:server}

place holder represented by concrete classes, produce by factory, parsed by engine.

lets look on the engine,




public string Parse(string command)
        {
            char[] commandChArray = command.ToCharArray(0, command.Length);


            int index = 0;


            StringBuilder outputMainCommand = new StringBuilder();


            // each place holder command may consist of place holder (aka command name) and property    
            // (aka command value).
            StringBuilder executeCommandName = new StringBuilder();
            StringBuilder executeCommandData = new StringBuilder();


         
            bool isCommandContext = false;
            bool isCommandData = false;
            bool isCommandName = false;


            int closeBracket = 0;
            while (index < commandChArray.Count())
            {
                switch (commandChArray[index])
                {
                    // encounter with {
                    case START_COMMAND_IDENTIFIER:
                        
                        closeBracket++;


                        if (!isCommandContext)
                        {
                            closeBracket = 1;


                            executeCommandName.Clear();
                            executeCommandData.Clear();


                            isCommandContext = true;
                            isCommandName = true;
                            isCommandData = false;
                        }
                        else
                        {
                            if (isCommandName)
                            {
                                executeCommandName.Append(commandChArray[index]);
                            }
                            else if (isCommandData)
                            {
                                executeCommandData.Append(commandChArray[index]);
                            }
                        }
                        break;
                   
                   // encounter with }
                   case END_COMMAND_IDENTIFIER:
                        
                       closeBracket--;


                       if (isCommandContext && closeBracket == 0)
                        {                            
                            try
                            {                                
                                string commandName = string.Empty;


                                if (executeCommandName != null)
                                {
                                    commandName = executeCommandName.ToString();
                                }


                                string commandData = string.Empty;
                                if (executeCommandData != null)
                                {
                                    commandData = executeCommandData.ToString();
                                }


                                if (!string.IsNullOrEmpty(commandName))
                                {
                                    string output = GetPlaceHolderHandler(commandName).FromPlaceHolder(commandData);


                                    outputMainCommand.Append(output);
                                }
                                else
                                    // common
                                {
                                    outputMainCommand.Append(commandChArray[index]);
                                }
                            }
                            finally
                            {
                                executeCommandName.Clear();
                                executeCommandData.Clear();


                                isCommandContext = false;
                                isCommandName = true;
                                isCommandData = false;    
                            }
                        }
                        if (isCommandContext)
                        {
                            if( isCommandName )
                            {
                                executeCommandName.Append(commandChArray[index]);
                            }
                            else if( isCommandData)
                            {
                                executeCommandData.Append(commandChArray[index]);
                            }
                        }
                                             
                        break;


                    case COMMAND_SEPERATOR_IDENTIFIER:


                        if (isCommandContext)
                        {
                            isCommandName = false;


                            if (isCommandData)
                            {
                                executeCommandData.Append(commandChArray[index]);
                            }


                            isCommandData = true;


                        }
                        else
                            // common
                        {
                            outputMainCommand.Append(commandChArray[index]);
                        }


                        break;


                    default:
                        if (isCommandContext)
                        {
                            if( isCommandName )
                            {
                                executeCommandName.Append(commandChArray[index]);
                            }
                            else if( isCommandData)
                            {
                                executeCommandData.Append(commandChArray[index]);
                            }
                        }
                        else
                        {
                            outputMainCommand.Append(commandChArray[index]);
                        }                       
                        break;
                }


                index++;
            }


            return outputMainCommand.ToString();
        }


Parse(string command) input example :  Data Source={connection_string:server}.

How to improve it ?
Add parallel to the parser, split the data to be parsed into command chunks and streaming the command value to the required command place holder, think on command defined from many place holder, all should be parsed.
Hello,

Some days ago, i was requested to add rules to our project, the rule have some rules: must be configured (outside of code), provide the  rule part of the current xml implementation, readable and of course, we dont have such time to do it, we have zero time.

First i decide to have this ability part of our flow xml data.

Rule definition lang should bring the ability to read/change/maintain/update/ add new functionllity in future/ etc the rule.

So, Rule should be xml or something closer.

In order to have within a xml document (my old and pretty xml files) a rule definition language, i had some ideas how to do it,

1. CDATA
2. Regular Expression
3. Json

I decided on json.

Why ?

CData, complex to read and maintains.

Regular expression, hard to maintain/read, not everyone familiar with it (its a pity but this is the reality)

So, i decide  to walk on Json,

Using json.net, it was very simple, just having xml with a json string, readable, simple and maintainable,

Before code, the rule should calculate date 30 days ago and 15 days ahead (this may change in production).

Let's code :

this is the json.net impl class


    [JsonObject(MemberSerialization.OptOut)]
    public class DatePlaceHolderDataItem : BasePlaceHolderDataItem
    {
        [JsonProperty]
        public Format Format { get; set; }


        [JsonProperty(PropertyName = "CalcBy")]
        public DateCalculation DateCalculation
        {
            get;
            set;
        }
    }


    [JsonObject(MemberSerialization.OptOut)]
    public class DateCalculateBy
    {
        [JsonProperty]
        public int Value { get; set; }
    }


....

i have defined new class BasePlaceHolderDataItem as follow :


public class BasePlaceHolderDataItem 
    {
        protected virtual Formatting SerializeFormattingType
        {
            get { return Formatting.None; }
        }


        public virtual string Serialize()
        {
            try
            {
                return JsonConvert.SerializeObject(this, SerializeFormattingType);
            }
            catch(Exception  exception)
            {
                throw new PlaceHolderException("Failed to Serialize place holder object.", exception);
            }
        }


        public static T Deserialize(string jsonDataItem)
        {
            if (string.IsNullOrEmpty(jsonDataItem))
            {
                return default(T);
            }


            try
            {
                return JsonConvert.DeserializeObject(jsonDataItem);
            }
            catch (Exception exception)
            {
                throw new PlaceHolderException( string.Format("Failed to Deserialize place holder string : {0}.", jsonDataItem), exception);
            }
        }
    }


lets examine the impl,

the FromPlaceHolder  identify place holder are parse it using the Deserialize method, invoke the ParsePlaceHolderByDataItem,  parse the object itself, simple and readable.

        public string FromPlaceHolder(string placeHolderData)

        {
            // DatePlaceHolderDataItem
            if (placeHolderData.StartsWith("{"))
            {
                DatePlaceHolderDataItem datePlaceHolderDataItem = DatePlaceHolderDataItem.Deserialize(placeHolderData);
               
                if( datePlaceHolderDataItem != null )
                {
                    return ParsePlaceHolderByDataItem(datePlaceHolderDataItem);
                }                
            }


            return ParsePlaceHolderByFormat(placeHolderData);            
        }


        private string ParsePlaceHolderByDataItem(DatePlaceHolderDataItem datePlaceHolderDataItem)
        {
            DateTime dateTime = DateTime.Now;


            if( datePlaceHolderDataItem.DateCalculation != null )
            {
                if( datePlaceHolderDataItem.DateCalculation.Year != null )
                {
                    dateTime = dateTime.AddYears(datePlaceHolderDataItem.DateCalculation.Year.Value);
                }
            }


            if (datePlaceHolderDataItem.DateCalculation != null)
            {
                if (datePlaceHolderDataItem.DateCalculation.Month != null)
                {
                    dateTime = dateTime.AddMonths(datePlaceHolderDataItem.DateCalculation.Month.Value);
                }
            }


            if (datePlaceHolderDataItem.DateCalculation != null)
            {
                if (datePlaceHolderDataItem.DateCalculation.Day != null)
                {
                    dateTime = dateTime.AddDays(datePlaceHolderDataItem.DateCalculation.Day.Value);
                }
            }


            if (datePlaceHolderDataItem.DateCalculation != null)
            {
                if (datePlaceHolderDataItem.DateCalculation.Hour != null)
                {
                   dateTime = dateTime.AddHours(datePlaceHolderDataItem.DateCalculation.Hour.Value);
                }
            }


            if (datePlaceHolderDataItem.DateCalculation != null)
            {
                if (datePlaceHolderDataItem.DateCalculation.Minute != null)
                {
                    dateTime = dateTime.AddMinutes(datePlaceHolderDataItem.DateCalculation.Minute.Value);
                }
            }


            if (datePlaceHolderDataItem.DateCalculation != null)
            {
                if (datePlaceHolderDataItem.DateCalculation.Second != null)
                {
                    dateTime = dateTime.AddSeconds(datePlaceHolderDataItem.DateCalculation.Second.Value);
                }
            }


            if( datePlaceHolderDataItem.Format != null && !string.IsNullOrEmpty(datePlaceHolderDataItem.Format.value) )
            {
                return dateTime.ToString(datePlaceHolderDataItem.Format.value);
            }


            return dateTime.ToString();
        }


using the Object oriented and json (also xml) capability give the developer to design & create generic platform of rule language.

Lets look on the xml :



  command.exe file.xml -s{current_data_time:{"Format":{"value":"MM/dd/yyyy"},"CalcBy":{"Day":{"Value":-30}}}} -e{current_data_time:{"Format":{"value":"MM/dd/yyyy"},"CalcBy":{"Day":{"Value":15}}}}}



Enjoy.

23 August 2010

"Exported mappings must come from the same importer" exception


Issue,


Look on the code below,


 ServiceDescriptionImporter descriptionImporter = new ServiceDescriptionImporter();
                descriptionImporter.ProtocolName = "Soap";
                descriptionImporter.AddServiceDescription(serviceDescription, null, null);
                descriptionImporter.Style = ServiceDescriptionImportStyle.Client;
                descriptionImporter.CodeGenerationOptions = 
                    System.Xml.Serialization.CodeGenerationOptions.GenerateProperties;


                foreach(XmlSchema sc in serviceDescription.Types.Schemas.ToList() )
                {
                    foreach (XmlSchemaObject service in sc.Includes)
                    {
                        if( service is XmlSchemaImport)
                        {
                            XmlSchemaImport schemaImport = service as XmlSchemaImport;


                                                   
                            XmlReader reader = new XmlTextReader(schemaImport.SchemaLocation);


                            descriptionImporter.Schemas.Add( XmlSchema.Read(reader, null));


                        }
                    }
                }

and



 private Assembly CompileAssembly(ServiceDescriptionImporter descriptionImporter)
            {
                // a namespace and compile unit are needed by importer
                CodeNamespace codeNamespace = new CodeNamespace();
                CodeCompileUnit codeUnit = new CodeCompileUnit();


                codeUnit.Namespaces.Add(codeNamespace);


                ServiceDescriptionImportWarnings importWarnings = descriptionImporter.Import(codeNamespace, codeUnit);

as you can in  the  first code fragment, i explicitly extracted the imported schema from the service description (wsdl wrapper), once the code did : ServiceDescriptionImportWarnings importWarnings = descriptionImporter.Import(codeNamespace, codeUnit); it throw an error, means 2 imported mapping exist, which one to use ? and it this case it throw an exception, what you should do, is , ignoring this code fragment :




 foreach(XmlSchema sc in serviceDescription.Types.Schemas.ToList() )
                {
                    foreach (XmlSchemaObject service in sc.Includes)
                    {
                        if( service is XmlSchemaImport)
                        {
                            XmlSchemaImport schemaImport = service as XmlSchemaImport;

                                                   
                            XmlReader reader = new XmlTextReader(schemaImport.SchemaLocation);

                            descriptionImporter.Schemas.Add( XmlSchema.Read(reader, null));

                        }
                    }
                }


So, damm, its still not working, once you did nothing and the schema (wsdl) has import to ref schema, its still failed to load ref schema element, why ? the servicedescription importer does not import the schema, you should do it manually, so how to do it, the first example present the way, but its still not working, so here the changes you need to do





            WebClient http = new WebClient();
              
            if (webServiceHelperData != null && 
                webServiceHelperData.NetworkCredential != null && 
                !string.IsNullOrEmpty(webServiceHelperData.NetworkCredential.UserName))
            {
                http.Credentials = new NetworkCredential(webServiceHelperData.NetworkCredential.UserName, 
                                                         webServiceHelperData.NetworkCredential.Password);
            }

            // parse wsdl
            serviceDescription = ServiceDescription.Read(http.OpenRead(url), false);
              
            // build an importer, that assumes the SOAP protocol, client binding, and generates properties
            ServiceDescriptionImporter descriptionImporter = new ServiceDescriptionImporter();
            descriptionImporter.ProtocolName = "Soap";
            descriptionImporter.AddServiceDescription(serviceDescription, null, null);
            descriptionImporter.Style = ServiceDescriptionImportStyle.Client;
            descriptionImporter.CodeGenerationOptions =
                System.Xml.Serialization.CodeGenerationOptions.GenerateProperties;
              
            // Download and inject any imported schemas (ie. WCF generated WSDL)          
            foreach (XmlSchema wsdlSchema in serviceDescription.Types.Schemas)
            {
                // Loop through all detected imports in the main schema
                foreach (XmlSchemaObject externalSchema in wsdlSchema.Includes)
                {
                    // Read each external schema into a schema object and add to importer
                    if (externalSchema is XmlSchemaImport)
                    {
                        Uri baseUri = new Uri(url);
                        Uri schemaUri = new Uri(baseUri, ((XmlSchemaExternal)externalSchema).SchemaLocation);

                        Stream schemaStream = http.OpenRead(schemaUri);
                        System.Xml.Schema.XmlSchema schema = XmlSchema.Read(schemaStream, null);

                        descriptionImporter.Schemas.Add(schema);
                    }
                }
            }

all we do, is adding the 
WebClient.




Enjoy

05 November 2008

How to get the last execution row in sql server and Cross apply


Have you ever think how to program better exception handling in your sql script, so this little article will teach how to do that, let's begin

The following query will give the last executed row in sql server

SELECT top 1 deqs.last_execution_time AS [Time], dest.text AS [Query]
FROM sys.dm_exec_query_stats AS deqs
CROSS APPLY sys.dm_exec_sql_text(deqs.sql_handle) AS dest
ORDER BY deqs.last_execution_time DESC


Notice : You can remove the top 1 and view all the last executed rows.

Cross & Apply Terms

The APPLY term let's you join a table to a table valued function.

No ON cluse used for this joining.

2 types of apply :

1. CROSS
Returns rows from the left side (Customers) if the table-valued-function returns rows.

2. OUTER
Returns all the rows on the left side (Customers) whether they return any rows in the table-valued-function or not. The columns that the table-valued-function returns are null if no rows are returned for the opposite row in the left side.

28 November 2007

Read this article , Dealt with top 20 GC articles.

26 November 2007

Repository, A new pattern

Most of the client -- Server application use a pattern called repository http://en.wikipedia.org/wiki/Repository.

Responsibilities :
- Cache (use it internally).
- reducing calling the server.
- Storage
- Provide base funtionllilty and abstract implementation over the repository,
- Offline warehouse.
- Middle tier between the client and server.

Repository problems,
- Decrease performance.
- Redundant calls to server.
- Not an abstract - Coupled to concrete implication.

The following new design of - ITEM SET repository, Give a new way of repository implementation.

So,

Item set


















To be continue...

26 June 2007

Think on public resource file, instead of using the resfgen tool which does no have the advatages of the ResXFileCodeGenerator, Here a link, the ultimate tool of creating resource as strongly type class.