xml介绍系列(10)

  • 作者:未知 来源:未知 添加时间:2006年7月3日 字体:

  • 系列之十八:如何使用xsl和正则表达式来验证数据的有效性(二)
    现在继续我在上一系列中介绍的例子。我们将实现一个简单的搜索机制,
    也许你的兴趣不是在获取书籍的标题而是在要获得整个书节点(note)上。
    那么使用下面这个函数就能够满足你的要求了
    public function getfilteredelements(activeelement as variant, regexpfilter as string, _
    optional querystring as string = "",optional isglobal as boolean=true, _
    optional ignorecase as boolean = true) as ixmldomnodelist
    dim re as regexp
    dim filterdoc as domdocument
    dim nodelist as ixmldomnodelist
    dim filterlist as ixmldomnodelist
    dim node as ixmldomelement
    dim basenode as ixmldomelement
    set re = new regexp
    on error goto errorhandler
    select case typename(activeelement)
    case "ixmldomelement"
    set basenode = activeelement
    case "domdocument"
    set basenode = activeelement.documentelement
    case else
    error 1001
    set getfilteredelements = nothing
    end select
    re.pattern = regexpfilter
    re.global=isglobal
    re.ignorecase=ignorecase
    if querystring = "" then
    set filterlist = basenode.selectnodes(".[textnode()]|./*[textnode()]")
    else
    set filterlist = basenode.selectnodes(querystring)
    end if
    for each node in filterlist
    if re.test(node.text) then
    node.setattribute "filter:filteredelementfound", "true"
    end if
    next
    set filterlist = basenode.selectnodes(".[@filter:filteredelementfound]|./*[@filter:filteredelementfound]")
    for each node in filterlist
    node.removeattribute "filter:filteredelementfound"
    next
    set getfilteredelements = filterlist
    exit function
    errorhandler:
    if err.number = 1001 then
    msgbox "document must be an xml document, or a document element."
    else
    error err.number
    end if
    end function

    下面是对这个方法的简单描述:
    getfilteredelements主要是用来获取一个xml的文档或则一个文档里面的节点,并且
    按照我们的需要转换它(包括所有的该节点的子节点),将转换后的节点放到一个
    列表类型ixmldomnodelist中.
    这个过滤器程序按次序对每个节点进行运用,如果一个节点的文本满足了表达式的话,
    那么这个节点就被做上一个临时属性的标记为filter:filteredelementfound
    (当然为了不和你自己的xml文档里已经存在的标志发生冲突,你可以把这个属性
    改成你需要的东西).
    一旦所有的节点都被检查完毕后,一个新的列表对象(仅仅只包含那些满足表达式的
    节点)被创建了。这些临时的属性会被删除掉,然后返回那些节点。

    如果你没有给这个函数输入查询参数的话,
    那么将获得整个文档的所有叶子节点(就是那些没有子元素的节点)
    如果你给这个函数输入查询参数的话,
    那么这个函数将返回满足条件的节点或则子节点
    例如,下面的代码将返回第一本书的标题和描述的节点和第四本书的
    描述节点
    dim bookxml=new domdocument
    bookxml.load("bookcatalog.xml")
    set nodelist=getfilteredelements(bookxml,"xml")
    而下面的代码将返回第一和第四本书的节点,然后你可以根据这些节点获取它们的
    子节点的属性。
    set nodelist=getfilteredelements(bookxml,"xml","/book")
    通常,你应该尽可能的定义一个xsl的查询过滤器(filter)
    因为它会只返回你需要的节点,会大大减少你需要处理的数据量。

    这个函数是xml "数据库"的一个运用实例,因为很多sql的开发者用熟悉了的
    参数(例如like)在xml中是没有等效的方法的,但是只要你在xml中能够熟练使用
    正则表达式,你会发现它能够实现很多like语句能够实现的功能。

    使用xsl转换验证数据
    正则表达式使用在xsl的转换中是一个强有力的验证数据有效的工具。
    例如,你想根据xml的数据生成一个显示书籍标题和描述的table
    当你使用基于dom版本(就是使用微软的那个模型xdom)的时候,xsl已经能够实现非常复杂的转换xml为
    html的功能了。
    在xsl的这个节点中<xsl:script>,允许你使用脚本语言。
    你可以在输出流中插入文本(但是目前你就不能够把一个dom节点输出到输出流中).
    xsl中默认的脚本语言是&#106avascript,
    在使用的过程中你需要注意的是,由于"/"在&#106avascript中是特殊字符,你需要使用
    "/"将其转意。
    代码如下:
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/tr/wd-xsl">
    <xsl:script language="&#106avascript"><![cdata[
    isvalidbooktopic=/xml/
    ]]></xsl:script>
    <xsl:template match="/">
    <xsl:apply-templates select="/book" />
    </xsl:template>
    <xsl:template match="book">
    <xsl:if expr="isvalidbooktopic.test(this.text)">
    <h1><xsl:&#118alue-of select="title"/></h1>
    <h2><xsl:&#118alue-of select="author"/></h2>
    <p><xsl:&#118alue-of select="description"/></p>
    </xsl:if>
    </xsl:template>
    </xsl:stylesheet>
    当然,你也可以改变你的xsl中的查询参数(例如上面例子中使用的参数是xml)
    一个直接的方法是生成一个参数实体"entities"
    例如下面的代码,你需要使用"%"字符来说明一个字符是参数。
    function setxslparameter(xsldoc as domdocument ,paramname as _
    string,param&#118alue as variant) as domdocument
    dim xsldoc as domdocument
    dim scriptnode as ixmldomelement
    dim re as regexp

    set re=new regexp
    re.global=true
    re.ignorecase=true
    re.pattern="%"+paramname
    for each scriptnode in xsldoc.selectnodes("xsl:script")
    scriptnode.text=re.replace(scriptnode.text,cstr(param&#118alue))
    next
    return xsldoc
    end function

    setxslparameter用来给xsl文档设置参数。
    当然你也可以不使用上面这个函数,直接在xsl的脚本里面修改这个参数,
    但是如果你使用了上面这个函数的话,可以让你的代码的可扩展性能更好。
    注意的是,xsl的代码将被上面这个函数所修改
    所以如果你想对相同的xsl对象使用不同的过滤器(就是不同的查询条件的话)
    需要使用xsl对象的clone(就是制作一个xsl的副本)方法。
    下面就是一个完整的例子
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/tr/wd-xsl">
    <xsl:script language="&#106avascript"><![cdata[
    isvalidbooktopic=/%searchstr/
    ]]></xsl:script>
    <xsl:template match="/">
    <xsl:apply-templates select="/book" />
    </xsl:template>
    <xsl:template match="book">
    <xsl:if expr="isvalidbooktopic.test(this.text)">
    <h1><xsl:&#118alue-of select="title"/></h1>
    <h2><xsl:&#118alue-of select="author"/></h2>
    <p><xsl:&#118alue-of select="description"/></p>
    </xsl:if>
    </xsl:template>
    </xsl:stylesheet>

    然后你就可以使用下面这段代码来修改这个参数了
    呵呵,我是搞asp的,下面这段代码就是写在你的asp的程序中的。

    set xmldoc=new domdocument
    set xsldoc=new domdocument
    xmldoc.load "catalog.xml"
    xsldoc.load "catalog.xsl"
    setxslparameter xsldoc, "searchstr", "pair-o-dice"
    response.write xmldoc.transformnode(xsldoc)

    同样,使用上面的方法,你就可以设置其他的参数了,例如浏览器的类型呀
    asp的查询参数呀,或则一个基于web的组件呀。

    使用正则表达式给xsl带来了强大的功能。
    虽然,使用这种通用性很强的方法在目前也许你不会看到能够给你带来很
    大的优势(主要是很少有人写xml的程序的说),但是在未来的编程过程中,
    你将会体会到它的强大威力了。

  • 上一篇:xml轻松学习手册(1)目录
  • 下一篇:xml介绍系列(9)
  • 最后更新时间:2024年12月22日
  • 返回页面顶端
ppdesk