刚开始,我沿用了XMLDOM的思维,企图通过给Script的函数传入XPath来解析XML文件。但是一直报告“Microsoft.JScript.JScriptException: Function expected
”的错误。例如下面的代码:
<Root>
<Members>
<Member id='1' name='Test1'/>
<Member id='2' name='Test2'/>
</Members>
<Logs>
<Log id='1' Date='2004-07-27' member='1'>Test Log</Log>
<Log id='1' Date='2004-07-28' member='2'>Test Log by Test2</Log>
</Logs>
</Root>
<Members>
<Member id='1' name='Test1'/>
<Member id='2' name='Test2'/>
</Members>
<Logs>
<Log id='1' Date='2004-07-27' member='1'>Test Log</Log>
<Log id='1' Date='2004-07-28' member='2'>Test Log by Test2</Log>
</Logs>
</Root>
我想根据传入的Log节点获取Log,并同时获取提交的member的name,于是我写了如下的代码:
<xsl:for-each select="Logs/Log"> <xsl:value-of select="JS:GetMemberName(/Members, @member)"/>
</xsl:for-each>
</xsl:for-each>
其中的JScript是:
<msxsl:script language="JScript" implements-prefix="UE">
function GetMemberName(members, requestID)
{
var memberList = members.selectNodes('Member');
}
</msxsl:script>
function GetMemberName(members, requestID)
{
var memberList = members.selectNodes('Member');
}
</msxsl:script>
但是,运行之后却报出“Microsoft.JScript.JScriptException: Function expected
”的错误。很显然,我使用的selectNodes这个函数不能被识辨。
折腾了很久,我突然想到,我获得的报错信息是来之.net runtime的,也就是说,也许我可以使用GetType()方法得到传入的members的类型,于是我把代码改成了下面的代码:
<msxsl:script language="JScript" implements-prefix="UE">
function GetMemberName(members, requestID)
{
return members.GetType().ToString();
}
</msxsl:script>
function GetMemberName(members, requestID)
{
return members.GetType().ToString();
}
</msxsl:script>
果然,返回的类型是:
XPathNodeIterator
查找这个类的相关信息,发现这个类有如下几个方法:
bool MoveNext()
XPathNavigator Current
int Count
int CurrentPosition
通过MoveNext可以获取其中的元素,而Current可以得到XPathNavigator对象。这一下简单了,通过XPathNavigator可以获得Member了。
于是,我把代码改成了如下的代码:
<msxsl:script language="JScript" implements-prefix="UE">
function GetMemberName(members, requestID)
{
while(members.MoveNext())
{
var innermember = members.Current.SelectChildren("Member", "");
while(innermember.MoveNext())
{
getUserID = innermember.Current.GetAttribute("id", "");
if(getUserID == requestID)
return innermember.Current.GetAttribute("name", "");
}
}
return "";
}
</msxsl:script>
function GetMemberName(members, requestID)
{
while(members.MoveNext())
{
var innermember = members.Current.SelectChildren("Member", "");
while(innermember.MoveNext())
{
getUserID = innermember.Current.GetAttribute("id", "");
if(getUserID == requestID)
return innermember.Current.GetAttribute("name", "");
}
}
return "";
}
</msxsl:script>
但是奇怪的是,我依然无法获取正确的名字,每次返回都是空字符。跟踪发现if(getUserID == requestID)没有正确运行。这时,我想到,可能传入的requestID同样是XPathNodeIterator对象,于是我把代码再修改了一下:
<msxsl:script language="JScript" implements-prefix="UE">
function GetMemberName(members, requestID)
{
var submitUserId = 0;
if(requestID.MoveNext())
{
submitUserId = requestID.Current.ToString();
}
while(members.MoveNext())
{
var innermember = members.Current.SelectChildren("Member", "");
while(innermember.MoveNext())
{
getUserID = innermember.Current.GetAttribute("id", "");
if(getUserID == submitUserId)
return innermember.Current.GetAttribute("name", "");
}
}
return "";
}
</msxsl:script>
function GetMemberName(members, requestID)
{
var submitUserId = 0;
if(requestID.MoveNext())
{
submitUserId = requestID.Current.ToString();
}
while(members.MoveNext())
{
var innermember = members.Current.SelectChildren("Member", "");
while(innermember.MoveNext())
{
getUserID = innermember.Current.GetAttribute("id", "");
if(getUserID == submitUserId)
return innermember.Current.GetAttribute("name", "");
}
}
return "";
}
</msxsl:script>
我增加了一个步骤,即从XPathNavigator中获取值,果然,运行成功了。
看来,在.net中,传入函数的节点被映射成了XPathNavigator对象,而且无论传入的是节点还是节点的属性。