IXsltContextFunction args seemingly passed wrong during Invoke

I have a user-defined XPath function implemented using a custom
context and the IXsltContextFunction interface.  For its arguments, it
accepts 3: { XPathResultType.Any, XPathResultType.Any,
XPathResultType.String }.  The function is called datediff, which
converts the arguments to DateTimes, and gives args[0] - args[1] in
the units specified by args[2] (e.g., "days", "months").  Anyhow, as
an example, Let's say I have the following XML file:

<root>
        <testnode DateVal="2008-12-05T00:00:00" TestName="Whatever" />
</root>

And I execute the expression: ' /root/
testnode[datediff("2008-12-25T00:00:00",@DateVal,"days") < 365]/
@TestName'
which should return the TestName attribute of any nodes whose DateVals
are within a year of 12/25/2008, give or take (for arguments sake,
let's just assume the function returns 0 if args[1] > args[0]).

The issue is that when the XPath function  (datediff) Invoke is
called, and I watch the args[] array, the second argument (@DateVal),
is an XPathNodeIterator with one XPathNavigator (as it should be),
but:

The XPathNavigator is the testnode element not the DateVal attribute.
Is this the expected behavior?  Why is an element node being passed in
as the argument, when, from the XPathExpression above, it's clearly
the attribute node that's being passed as an argument to the function?

By the way, I realize that I can pass "string(@EndDate)" as the second
argument, which works fine, but a function I'm building now that
returns a set representing a cross-product of node sets will need the
ability to traverse through attribute nodes.
0
12/5/2007 10:30:08 PM
dotnet.xml 7266 articles. 0 followers. Follow

2 Replies
788 Views

Similar Articles

[PageSpeed] 20

That's really weird. I'd like to hear the answer too.
Btw, can you provide minimal repro?

--
Oleg

jakebbohio wrote:
> I have a user-defined XPath function implemented using a custom
> context and the IXsltContextFunction interface.  For its arguments, it
> accepts 3: { XPathResultType.Any, XPathResultType.Any,
> XPathResultType.String }.  The function is called datediff, which
> converts the arguments to DateTimes, and gives args[0] - args[1] in
> the units specified by args[2] (e.g., "days", "months").  Anyhow, as
> an example, Let's say I have the following XML file:
> 
> <root>
>         <testnode DateVal="2008-12-05T00:00:00" TestName="Whatever" />
> </root>
> 
> And I execute the expression: ' /root/
> testnode[datediff("2008-12-25T00:00:00",@DateVal,"days") < 365]/
> @TestName'
> which should return the TestName attribute of any nodes whose DateVals
> are within a year of 12/25/2008, give or take (for arguments sake,
> let's just assume the function returns 0 if args[1] > args[0]).
> 
> The issue is that when the XPath function  (datediff) Invoke is
> called, and I watch the args[] array, the second argument (@DateVal),
> is an XPathNodeIterator with one XPathNavigator (as it should be),
> but:
> 
> The XPathNavigator is the testnode element not the DateVal attribute.
> Is this the expected behavior?  Why is an element node being passed in
> as the argument, when, from the XPathExpression above, it's clearly
> the attribute node that's being passed as an argument to the function?
> 
> By the way, I realize that I can pass "string(@EndDate)" as the second
> argument, which works fine, but a function I'm building now that
> returns a set representing a cross-product of node sets will need the
> ability to traverse through attribute nodes.
0
foo2109 (4)
12/6/2007 9:05:55 PM
On Dec 6, 4:05 pm, Oleg Tkachenko <f...@dummy.com> wrote:
> That's really weird. I'd like to hear the answer too.
> Btw, can you provide minimal repro?
>
> --
> Oleg
>
> jakebbohio wrote:
> > I have a user-defined XPath function implemented using a custom
> > context and the IXsltContextFunction interface.  For its arguments, it
> > accepts 3: { XPathResultType.Any, XPathResultType.Any,
> > XPathResultType.String }.  The function is called datediff, which
> > converts the arguments to DateTimes, and gives args[0] - args[1] in
> > the units specified by args[2] (e.g., "days", "months").  Anyhow, as
> > an example, Let's say I have the following XML file:
>
> > <root>
> >         <testnode DateVal="2008-12-05T00:00:00" TestName="Whatever" />
> > </root>
>
> > And I execute the expression: ' /root/
> > testnode[datediff("2008-12-25T00:00:00",@DateVal,"days") < 365]/
> > @TestName'
> > which should return the TestName attribute of any nodes whose DateVals
> > are within a year of 12/25/2008, give or take (for arguments sake,
> > let's just assume the function returns 0 if args[1] > args[0]).
>
> > The issue is that when the XPath function  (datediff) Invoke is
> > called, and I watch the args[] array, the second argument (@DateVal),
> > is an XPathNodeIterator with one XPathNavigator (as it should be),
> > but:
>
> > The XPathNavigator is the testnode element not the DateVal attribute.
> > Is this the expected behavior?  Why is an element node being passed in
> > as the argument, when, from the XPathExpression above, it's clearly
> > the attribute node that's being passed as an argument to the function?
>
> > By the way, I realize that I can pass "string(@EndDate)" as the second
> > argument, which works fine, but a function I'm building now that
> > returns a set representing a cross-product of node sets will need the
> > ability to traverse through attribute nodes.

Sure.

Here's trivial example that will output data about a node passed in:

Create a class to host the function:

    public class XPathFuncTest : IXsltContextFunction
    {
        XPathResultType[] IXsltContextFunction.ArgTypes
        {
            get
            {
                return new XPathResultType[] { XPathResultType.Any,
XPathResultType.String };
            }
        }

        int IXsltContextFunction.Minargs
        {
            get
            {
                return 2;
            }
        }

        int IXsltContextFunction.Maxargs
        {
            get
            {
                return 2;
            }
        }

        XPathResultType IXsltContextFunction.ReturnType
        {
            get
            {
                return XPathResultType.String;
            }
        }

        object IXsltContextFunction.Invoke(XsltContext xsltContext,
object[] args, XPathNavigator docContext)
        {
            if (args[0] as XPathNodeIterator != null)
            {
                XPathNodeIterator objNI = (XPathNodeIterator)args[0];
                if(objNI.Count == 0)
                    return "null";
                if(objNI.Current == null)
                    objNI.MoveNext();
                switch (args[1].ToString())
                {
                    case "type":
                        return objNI.Current.NodeType.ToString();
                        break;
                    case "name":
                        return objNI.Current.Name;
                        break;
                    case "value":
                    default:
                        return objNI.Current.Value;
                        break;
                }
            }
            return "";
        }

    }

And then a simple CustomContext implementation:

    public class CustomXPathContext : XsltContext
    {
        private Dictionary<string, IXsltContextFunction>
objFunctionLookup = new Dictionary<string, IXsltContextFunction>();

        public CustomXPathContext(NameTable objNT)
            : base(objNT)
        {

        }

        public CustomXPathContext() : this(new NameTable()) { }

        public void RegisterCustomFunction(string FunctionName,
IXsltContextFunction FunctionProcessor)
        {
            if (!objFunctionLookup.ContainsKey(FunctionName))
                objFunctionLookup.Add(FunctionName,
FunctionProcessor);
        }

        public NameValueCollection VariableMapping
        {
            get { return objVarMapping; }
            set { objVarMapping = value; }
        }

        public override IXsltContextFunction ResolveFunction(string
prefix, string name, XPathResultType[] ArgTypes)
        {
            if (objFunctionLookup.ContainsKey(name))
            {
                return objFunctionLookup[name];
            }
            return null;
        }

        public override IXsltContextVariable ResolveVariable(string
prefix, string name)
        {
            return null;
        }

        public override bool Whitespace
        {
            get { return true; }
        }

        public override bool PreserveWhitespace(XPathNavigator node)
        {
            return true;
        }

        public override int CompareDocument(string baseUri, string
nextbaseUri)
        {
            return 0;
        }
    }

Finally, a quick and dirty console app to do the testing:

namespace TestApp
{
    class Program
    {
        static void Main(string[] args)
        {
            MemoryStream ms = new MemoryStream();
            StreamWriter sw = new StreamWriter(ms);
            sw.Write("<root><testnode DateVal=\"2008-12-05T00:00:00\"
TestName=\"TestNameAttribute\" /></root>");
            sw.Flush();
            ms.Position = 0;

            XPathDocument objTestDoc = new XPathDocument(ms);
            XPathNavigator objNav = objTestDoc.CreateNavigator();

            //Create the context, register the nodeinfo function
            CustomXPathContext objContext = new CustomXPathContext();
            objContext.RegisterCustomFunction("nodeinfo", new
XPathFuncTest());

            //Should return "TestNameAttribute", but return an empty
string
            System.Xml.XPath.XPathExpression objCompiled1 =
System.Xml.XPath.XPathExpression.Compile("string(/root/
testnode[nodeinfo(@DateVal,'type') = 'Attribute']/@TestName)");
            objCompiled1.SetContext(objContext);
            Console.WriteLine("@DateVal NodeType == Attribute: " +
objNav.Evaluate(objCompiled1).ToString());

            //Should return an empty string, but returns
"TestNameAttribute"
            System.Xml.XPath.XPathExpression objCompiled2 =
System.Xml.XPath.XPathExpression.Compile("string(/root/
testnode[nodeinfo(@DateVal,'type') = 'Element']/@TestName)");
            objCompiled2.SetContext(objContext);
            Console.WriteLine("@DateVal NodeType == Element: " +
objNav.Evaluate(objCompiled2).ToString());

            //This returns "Root" as the node type, making me think
the the node argument passed to Invoke is identical to the context
node, for some reason:
            System.Xml.XPath.XPathExpression objCompiled3 =
System.Xml.XPath.XPathExpression.Compile("nodeinfo(/root/testnode/
@DateVal,'type')");
            objCompiled3.SetContext(objContext);
            Console.WriteLine("@DateVal NodeType: " +
objNav.Evaluate(objCompiled3).ToString());

            Console.ReadKey();
        }
    }
}

Just run the console app to reproduce the behavior.  Maybe I'm crazy,
and it's working how it is supposed to, but the argument passed to
args[], when the argument is a nodeset, seems to always be the context
node, as opposed to the specified node.

-- Nate
0
12/7/2007 3:21:22 PM
Reply:

Similar Artilces:

YYYY format displaying wrong date
I admit I'm confused by this. I'm using Excel '97 (Yes, yes, I know. Upgrade. But this is a client's system over which I have no control.) The client supplied me with a spreadsheet containing a lot of data. I need to make the data consistent for it to be usable. There is a column containing only the year which is currently defined as Text. I want the data to be Date type with a "YYYY" format. I managed to do this somehow in another spreadsheet of similar data. In the spreadsheet I'm currently working on, when I change the column to Date type with "YYY...

How to open a form with multiple Args
This line of code is suppose to open another form and use these OpenArgs as values in some of the controls in the new form. DoCmd.OpenForm "Invoice by Dates", acNormal, acWindowNormal, OpenArgs:=Me.txtStartDate.Value & "," & Me.txtEndDate.Value & "," & Me.cmbVendor.Value & "," & Me.cmbReviewer I am able to get it to work for the first two Args, i.e. Me.txtStartDate.Value & "," & Me.txtEndDate.Value but I can't get the other Args to show on the 2nd form. I was using this codes, commaOne = InStr...

using wrong smtp server
here is my situation: 2 exchange 2003 servers, one on local network that handles mail, and public folders, and one in the dmz that should only be handling internet mail inbound and outbound. Inbound internet mail works just fine. Outbound mail is going out through the exchange 2003 server that is in my local network though. This works most of the time, but if anyone sends to anyone who requires a reverse dns record to receive mail will not accept mail from us because the reverse record goes to out to the server in the dmz. What do I need to do to get all outbound mail to go out through ...

Syntax for "OR" in WHERE clause passing parameters from C# ASP.NET
Hello Community I am passing parameters SQL Server from an C# ASP.NET app. When creating the query I have need to use an “or” operator after the Where clause when comparing values. Does anyone know the syntax for this type of thing? Below is the code: public DataSet getCustomer(string Addr, int PhoneNo) { string strSQL = " select distinct a.firstname + ' ' + a.lastname as Name"; strSQL += " from table1 a Join Table2 b "; strSQL += " on a.id = b.id "; ...

IXsltContextFunction.Invoke
When creating a function in xpath with IXsltContextFunction, if the return type is nodeset, what do you actually return from the Invoke function? A XmlNodeList? XPathNodeIterator? public System.Xml.XPath.XPathResultType ReturnType {get{ return System.Xml.XPath.XPathResultType.NodeSet; }} TIA Colin Colin Savage wrote: > When creating a function in xpath with IXsltContextFunction, if the return > type is nodeset, what do you actually return from the Invoke function? A > XmlNodeList? XPathNodeIterator? Sure it's XPathNodeIterator. -- Oleg Tkachenko XML Insider http://www.t...

Visio is extremely slow to respond (mouse seems to stick)
This only happens in Visio 2003 Pro; while authoring a document, objects placed on the page do not respond to click commands (such as double-click to enter text) and the objects get stuck in drag-mode after a single click. Overall Visio performance is extremely poor... Sometimes it can take 10 to 20 seconds for the application to execute the actions I'm trying to perform. It's certainly not the hardware platform, my system is far-beyond minimum requirements - no other applications stall like this. I'm not certain why this is happening. I've reinstalled Visio but it doesn&...

Emails going to wrong user
I have an outlook user that when I try to send email to it goes to someone else in the company. I have looked over Exchange and AD properties and there is no rule set up to send it to another mailbox. It only happens with my email address, which is on another email domain than his. The only thing I can think of is that he created a rule in outlook, but he says that he has not. He also checks his mail from multiple pc's so it would be hard to look through each outlook client for a rule. Also, if a rule is created on one instance of outlook on one pc would the rule show up if the user...

Monthly Budgeted amount wrong in MSMoney 2003 deluxe
I have a budget with some life insurance bills in the Insurance : Life category. When I am in the "Enter your expenses section of the budget, It looks like this: Company 1 Every three months 72.28 Company 2 Every three months 64.11 Company 3 Yearly 60.00 Compnay 4 Yearly 45.60 This averages out to 54.26 monthly which is correct. It displays this below these in the Subtotal row,,, BUT,,,,,, When i I look at my budget in the "Review Your Current Budget Status" page for the current month , it shows the actual amount fo...

pass comboboxvalue to another userform
Hi, can get this ting right. Maybe you know how to? In a userform is a combobox which value I want to keep using in a second userform for a combobox over there. Goal: choose value in userform1 / combobox1 let say 4 unload userform1 show userform 2 with combobox2 filled with the chosen valu in this case 4 Do you kow how to achieve this? Thanks, jan Jan This could be passed as a public variable to another module prior to unloading the form. (Unloading the form removes it from memory including any objects values. Alternatively, you could simply 'Hide' the form (UserformName.Hid...

Seems Simple But I Cant Get It !
THIS IS MY PROBLEM: i got a row with alpha_num entries(e.g RN1, P2, EN4) i wan to count the number of entries that has the number 1 behind the first two alphabet. -- cjjoo ------------------------------------------------------------------------ cjjoo's Profile: http://www.excelforum.com/member.php?action=getinfo&userid=26916 View this thread: http://www.excelforum.com/showthread.php?threadid=471016 Hi! Try this: =SUMPRODUCT(--(MID(A1:F1,3,1)="1")) Biff "cjjoo" <cjjoo.1w07ab_1127801106.0035@excelforum-nospam.com> wrote in message news:cjjoo.1w07a...

Import to wrong place
When I imported my .pst I accidently dumped it into "personal folders" choice instead of Outlook Today [personal folders]. Therefore I now have two each of inbox, calendar, notes, etc. The folders under Outlook Today in the folder view are blank. The folders unders the added personal folder is where the information is now. I want to move it all to Outlook Today [personal folders]. I've tried un-install and re-install the entire Office program, but the folder settings end up in the same place. I can move the personal folders to Outlook Today but it won't let me &q...

Passing Information to and from Forms
My goal; have the user select choices on a page of checkboxes and capture the labels for those boxes and concatenate them into one large string. When I use brute force like multiple if then statements in the property definition behind the form to check the value of a each checkbox by name for true/false ala if chkBoxPrimary=True then MyBins=MyBins+"Primary" then everything works. Problem is i have 50 checkboxes so I want to capture the caption and add that to my string. so I cycle thru the checkboxes and if they are true I add the caption. unfortunately i get an er...

Spell Check should notify me if I keep spelling a word wrong
Spell Check is a fantastic tool, however, is not helping us to improve our grammar and spelling. As more and more children are using computers as a tool for education, their misspelled words are constantly being corrected (sometimes automatically) by Word which is not encouraging them to learn how to spell and use grammar correctly. It would be great if Word could notify us if we keep spelling the same word incorrectly or keep making the same grammar errors. I would like to see a pop up that indicated how many times I have spelled a word incorrectly. As an advanced tool it...

Open Args PivotChart Form
looked in help but can't seem to locate what is the opening argument for a pivotchart to open in graph chart form... made a button to open it - and it opens it in form view not chart view....tried acChart or acChartView but no luck.....kind of drives me crazy when I can't locate info that I know should be findable...... used a macro instead which works...but would like to know still......tia -- NTC ...

Passed my Exam.
I have finally passed my exam, 4th time lucky. I got 72, 70,78 and 82% in each of the exam. I am curios, if anyone else had a similar difficulty with the exams? Your Curiously Al Plz... I need ur help do u have a model of exam... to study? >-----Original Message----- >I have finally passed my exam, 4th time lucky. > >I got 72, 70,78 and 82% in each of the exam. I am curios, >if anyone else had a similar difficulty with the exams? > >Your Curiously > >Al >. > Could you explain why the exams are hard? i have to take 3 crm exams and keep hearing about how...

CCheckListBox passing messages?
Hey! I have this CDialog in which I have a CCheckListBox. I wish to add buttons to the listbox so I create CButtons using the listbox as a parent. Everyting is just fine until I wish to capture the BN_CLICKED event from the buttons. It seems that the message doesn't get passed on from the listbox. How do I solve this? Thanks /Marcus "Marcus Seyffarth" <marcus@ettsexett.com> wrote in message news:eBAE7vNwEHA.3416@TK2MSFTNGP09.phx.gbl... > Hey! > > I have this CDialog in which I have a CCheckListBox. I wish to add buttons > to the listbox so I create CBu...

Seemingly impossible task
In the example below I am trying to determine the rows that contain duplicate account numbers. I am thinking that if I could do an IF/AND function I could get the information I want. The second column gives me the results I want, I just can't get there. Basically if an account in column one is also located in column 3 and column 4 is a "91" I would like a return of no. If an account in column 1 is in column 3 and column 4 is a "92" I would like a return of yes. If an account in column 1 is not in column two, regardless of what is in column 4, I would like a ...

csv format is wrong in Denmark
When I make csv file from excel 2007, then I do not get a comma-separated file. The cells are separated with a semicolon and the the normal dot in numbers is a comma. This is the case when you live in Denmark. The problem with the "Danish" excel csv format is that we can not export it to what ever we want. If I want to use it in Microsoft Visual Studio Team System, for a unit test, then it does understand the format. Is it possible in Office to save in correct cvs format? This is something to be done with the Windows setting. Start>Settings>Control Panel>...

What's wrong with this code
I have the following block of code, i notice by using system task manager MEM Usage ,also using Process Explorer from SysInternals that: 1: CString strImage; 2: GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); 3: SIZE sz; 4: sz.cx = ::GetSystemMetrics(SM_CXSCREEN); 5: sz.cy = ::GetSystemMetrics(SM_CYSCREEN); 6: HDC hdc = ::GetDC(::GetDesktopWindow()); 7: Graphics *g1 = new Graphics(hdc); 8: Image *image = new Bitmap(sz.cx,sz.cy,g1);// 9: Graphics *g2 = Graphics::FromImage(image); 10: delete image; before the line 8 the mem is (420616 KB) after call line 8 the mem be (...

Forms created in Word 2003 that I can't seem to edit in Word 2007
My IT department recently upgraded me to Office 2007. Much of it I absolutely love. But it is taking some getting used to. Here is my issue. I created many forms for my department at work in Word 2003 with form fields. Now, when I open them I cannot access many of the functions on the "ribbon" such as "Font", "Paragraph" etc. I have done quite a bit of searching through forums online and not been able to solve the issue. I have found the "Protect" tab and set it to unrestricted, but I'm at a loss at this point and completely frus...

IXsltContextFunction args seemingly passed wrong during Invoke
I have a user-defined XPath function implemented using a custom context and the IXsltContextFunction interface. For its arguments, it accepts 3: { XPathResultType.Any, XPathResultType.Any, XPathResultType.String }. The function is called datediff, which converts the arguments to DateTimes, and gives args[0] - args[1] in the units specified by args[2] (e.g., "days", "months"). Anyhow, as an example, Let's say I have the following XML file: <root> <testnode DateVal="2008-12-05T00:00:00" TestName="Whatever" /> </root> And ...

Spam getting passed junk email filter
I have 5 copies of Outlook 2003 in corp. enviroment and they were doing a great job filtering out spam and then last we it was like the filter was turned off, but it is still set on high, any suggestions? adam@bruceoakley.com ...

Custom IXsltContextFunction behaves differently within a predicate
I have implemented a custom XPath function that is used to retrieve an XPathNodeIterator over an XmlDocument (other than the primary document being queried) specified by filename. This function works in an expression like: /a:Doc/a:Value + custom:GetDoc('doc2.xml')/b:Doc/b:Value But the custom function will not even be invoked if used in an expression like: /a:Doc/a:Value[. = custom:GetDoc('doc2.xml')/b:Doc/b:Value] These expressions are being compiled and then evaluated against an XPathNavigator over XmlDocument. I've found that within the CompiledXPathExpr's que...

OnDirty Doesn't seem to be working
I have a form which I use to bring up client records and if necessary make changes to them. I also have a log table which I want to update only when changed to a client record is made. I have tied an append query to the AfterUpdate event of the form, but it updates the table even when no change is made to a client record. When I tie the append query to the OnDirty even of the form it doesn't seem to run at all. In fact I placed a Debug.Print statement in the OnDrity event, then open the form to a client record and make changes to the phone number, expecting to see my Debug message in th...

Mail delivered to the wrong addresses
Hello, I have a very weird problem with our Exchange server. We have just migrated our users from one domain to a new domain. We created a new domain on completely new servers an imported all users from the old one - we didn't migrate any other settings. The problem is that a very small percentage of incoming mail is being delivered to a wrong address. An example could be that someone is sending a mail to ehandel@commitment.dk but the mail is delivered to an address that doesn't exist called tje2@commitment.dk. This address once existed in the old domain and was used for test ...