Chinaunix首页 | 论坛 | 博客
  • 博客访问: 9240788
  • 博文数量: 1227
  • 博客积分: 10026
  • 博客等级: 上将
  • 技术积分: 20273
  • 用 户 组: 普通用户
  • 注册时间: 2008-01-16 12:40
文章分类

全部博文(1227)

文章存档

2010年(1)

2008年(1226)

我的朋友

分类: C/C++

2008-04-02 14:57:42

下载本文示例代码


在Visual Studio® .NET中至少有两种方法可以让你使用 IntelliSense®。一种方法是购买一个第三方的插件,如 ActiveState Visual XSLT;另一种方法是利用包含在Visual Studio .NET中,由 XML Schema 定义驱动的 XML IntelliSense。前一种方法需要花钱,后一种方法仅仅需要你找到一个用于 XLST 的 XML Schema 定义。
  遗憾的是,XLST规范的创建者们在他们第一次制定规范时,并没有将一个正式的XML Schema定义包含到规范中,所以,你无需在W3C 的网站上徒劳地寻找。然而,多年以来,出现了一些供个人或企业使用的XSLT Schemas。其中我找到的最好的一个是:。
  Visual Studio® .NET为它所知道的所有XML Schema提供了XML IntelliSense。Visual Studio® .NET能够在指定的工程中自动的识别XML Schema的定义,也可以在目录:C:\Program Files\Microsoft Visual Studio .NET 2003\Common7\Packages\schemas\xml下找到一套全局性的XML Schema定义。你将会注意到,在这个目录下存在几个Schema文件,其中也包括XML Schema的。
  一旦得到了你想用于 IntelliSense 的 XSLT Schema。接着只要简单地将它添加到你的工程中,或者拷贝到目录"C:\Program Files\Microsoft Visual Studio .NET 2003\Common7\Packages\schemas\xml"下。为了测试IntelliSense,可以从 File 菜单中选择 New | File | XSLT File来创建一个新的 XSLT 文件。然后,你应该可以看到一个包含了一个空样式单 Transform(指向 )元素的XSLT模版文件。把你的光标移到样式单开始和结束标记之间,输入"<",那么,你将可以看到IntelliSense的自动弹出,列出允许的XSLT元素信息。
  Visual Studio® .NET使用元素的XML namespace来检测使用那个schema。举个例子,如果你新建的XSLT使用"xsl:transform"作为根节点(代替了"xsl:stylesheet"),那么IntelliSense将会在你再次指定相同的namespace后,作同样的工作。
  Visual Studio® .NET甚至能够帮助你在所以已知的namespace名称中选择正确的namespace。注意,当我把XSLT namespace放到全局的schema目录之后,Visual Studio® .NET已经在列表中包括了它( 如Figure 1)


Figure 1

  这个功能可以对任何XML Schema定义生效。如果你有一些自定义的,需要经常使用的schema,那么,你就会想在Visual Studio? .NET中使用这个有些利用不足的特点。
 


是的,在Visual Studio .NET的安装目录下,可以找到一些新文件的模版。从文件菜单创建新文件时,能够在目录"C:\Program Files\Microsoft Visual Studio .NET 2003\Common7\IDE\NewFileItems"下找到一些全局性的模版。另外,在不同语言的子目录下,还可以找到一些针对特定工程和语言的模版(参看"C:\Program Files\Microsoft Visual Studio .NET2003\VC#\CSharpProjectItems for C#-specific templates")。
  新XSLT文件的模版被命名为XSLTFile.xslt。简单地修改这个文件就可以适应你的需要。如果你和我一样,更喜欢使用transform(而不是stylesheet),喜欢前缀"xml"(而不是缺省声明的namespace),你可以将缺省的XSLT模版修改成像下面的样子:


  
这样的话,每一个使用Visual Studio .NET创建的新XSLT文件都会像这个模版一样。



试图在一个XSLT转换中输出XSLT元素是有问题的,因为,你会引发namespace的冲突。例如,考虑下面一段XSLT的片段,它尝试在根模版中输出一个xsl:transform元素。

    
        
        
        
            
               ???
            
        
    
      
  问题出来了,我试图输出的transform元素与“真实”的transform元素在一个名字空间中,而根据 XSLT 处理器设计,它将“真实”的transform元素理解成程序的 开始标志。所以,当处理器发现嵌套的xsl:transform元素(用于输出的),它认为它是另外一个程序的结构。
  这里有两种方法来解决这个问题。第一种是使用xsl:element和xsl:attribute元素来动态的生成XSLT元素,如 Figure 2 所示。
  现在,因为我动态的生成了XSLT元素(不要把它们写到模版中),namespace冲突就没有发生了。但是,如你所见,这个过程是冗长乏味的,而且可读性很差,更不要说测试和验证了。
  另外一种方法是使用XSLT提供的namespace别名。XSLT有一个xsl:namespace-alias元素,它能有效地欺骗处理机,使其相信我要输出的XSLT元素是在和真实的XSLT不同的namespace中,并且构造这个文档。xsl:namespace-alias的语法示例如下:
      
  你使用这个元素来指定映射“真实的”namespace的namespace前缀(使用result-prefix属性)和临时的别名(使用stylesheet-prefix属性)。例如:下面的转换向处理机说明前缀“alias”在转换中作为别名。注意,它被映射为和XSLT中不同的namespace(我只是在XSLT namespace前面附加了“alias”)。现在,我能简单的使用前缀“alias”来书写XSLT转换,你可以看到,这样的处理使转换的读写都更加的方便,见方便,见Figure 3
  那么,当XSLT处理机执行转换并且产生输出文档时,它使用“result-prefix”属性中定义的字符替换前缀“alias”(例子是“xsl”)。从此,输出文档就包含了正确的XSLT namespace,就像你在Figure 3中看到的一样。

    ...
    
        
        
            
            
        
        
    
      
如果你有很多的XSLT库需要经常维护和升级,那么这个功能将会非常的有用。



内建的编号功能是XSLT保持得最好的秘密之一,很遗憾人们对这个功能知之甚少,这个功能可以简化许多转换使用的复杂的编号任务。XSLT提供一个名为xsl:number的元素:它使 我们将格式化好的编号插入到结果文档成为可能。 你可以使用该元素的下列各种属性去影响编号在结果文档中产生的方式以及格式化处理的方式。
      
  xsl:number元素首先求得在值属性中提供的表达式的值,接着结果对象被转换为某个编号,就像调用XPath 的 number 函数一样。 编号然后被四舍五入到 为一整数,并依照最后五个属性值(format, lang, letter-value, grouping-separator, and grouping-size)被格式化。xsl:number 的所有属性描述 参见 Figure 4
下面是一个XSLT语句例子:

这个表达式在结果树中显示如下:
      1,666,667       
  但是通常情况下都省略值属性,由xsl:number自动计算。当你不指定值属性时,xsl:number计算并以当前节点位置为值。level, count, 和 from 属性 影响当前节点位置的计算方式。from属性的计算模式确定了从树的何处开始计算,而count属性的计算模式确切给出应该计算哪个节点,level 属性指定 了在计算过程中应该考虑源树的哪些层次。
  level可能的值有三种:“single”、“any”和“multiple”。single值计算目标节点之前的兄弟节点(即 XPath 的前兄弟轴。译者注:preceding-sibling表示当前节点的所有在它之前的兄弟节点),如果当前节点 与计算模式匹配,或者没有指定计算,那么当前节点即为目标节点。否则,目标节点就是与该计算模式匹配的第一个祖先节点。与from模式匹配的第一个祖先 节点(当前节点的)确定了计数开始节点始于何处。只有那些从开始节点到当前节点之间的节点被计算。
  文档次序中当前节点之前节点的“any”节点计数值由计算模式确定,(即 XPath 的preceding 轴和 ancestor-or-self 轴的合并)。 与from模式匹配的(当前节点之前的)第一个节点指定计算从哪个节点处开始。只有那些从开始节点到当前节点之间的节点被计算。
  “multiple”计算产生一个序列编号,每个编号的产生方式与产生单一层次的计数值相同(例如 1.1.1 , 1.1.2, 1.2.1等等)。与 count 模式匹配的最外 层的祖先的计数值为序列的第一个编号。接下来次外层祖先的计数值为序列的第二个编号,如此类推。与 count 模式匹配的最里层祖先计数值为序列的最后一个编号。每一个祖先 的计数值的确定与单层计数一样。
  下面让我们看看几个例子。下面是一个包含了sample book 结构的XML文档。

  
    
      

This is some sample text.

...
  在这个特定的 schema 中,books元素可能包含几个book元素,每个book元素可能包含多重chapter元素,每个chapter元素有可能包含多重section元素。下面的转换使用默认的xsl:number功能(level=”single”)来计算 books、chapters 和 sections 的 编号。



.


    ...

  这个转换产生的文本见 Figure 5(添加空白字符为提高可读性)。注意book、chapter和section计数是被独立的保持下来。现在参看一下Figure 6中的使用level=“any”的转换。
  在“any”方式下,chapter编号不再在book的包含范围之内,section编号也不再在chapter的包含范围之内。现在的chapter和sectoin在整个文档中从开始到结束以连续的方式被编号,见Figure 7。如果你想让每个编号项包含祖先级别编号(例如 1.2.1 ),那么你使用level的“multiple”值。
  在“multiple”方式下,你具体指定出一个模式,显示的在诸多祖先中你想计数哪些节点,如下所示:

. 



.



  注意到你不必为book元素作任何专门的处理,因为它是最外面直到计数结束的元素。然而,对chapter元素,你必须具体指定出你想计数book和chapter的元素;对section元素你也必须具体指出你想计数section、chapter和book的元素。这个例子产生的编号列表见Figure 8
  当使用这些技术的时候,你也可以使用 format 属性去控制怎样格式化编号。在前面的例子中,硬编码句号使之跟随在产生的编号数字之后, 我可能已经通过使用下面的format属性完成了这些:





  你可能也想在你的编号schema中使用罗马数字(例如:I、II、III、IV等等)或者按字母顺序的字符(例如:A、B、C、D等等),这是可行的,要通过详细指定一个专门的format属性值。Figure 9提供了一些格式表示的例子以及对每种格式编号序列的实例值。例如Figure 10里的转换,使用罗马数字为book编号,用按字母顺序的字符为chapter编号,用阿拉伯数字为section编号。
  这种转换产生了象前面同样的编号列表,但格式化的层次不同。
I. Sample Book
  I.A. Sample Chapter
    I.A.1.Sample Section
    I.A.2.Sample Section
    I.A.3.Sample Section
  I.B. Sample Chapter
    I.B.1.Sample Section
    ...
II. Sample Book
  II.A. Sample Chapter
    II.A.1.Sample Section
    II.A.2.Sample Section
    ... 
  正如你看到的,只要你理解了XSLT提供的编号功能是怎样运作的,它对你的转换是一个强大而又灵活的补充。



在一个XSLT处理器执行一个与给定源文档相反的转换时,它首先从双方文档中去除掉所有纯空白文本节点(white space-only text nodes)。一个空白文本节点是一个仅包含空格、制表符和回车等的文本节点。 开发人员在他们需要在结构树中明确地输出空白的时候经常被绊倒,因为他们通常首先试图在它们的转换中直接地键入空白,然而,除非文本节点中也包含了非空白字符,否则它将会在转换开始前被去除掉。例如,参看一下下面企图在在两个xsl:value-of 声明中输出一个空格字符的转换(看起来first和last会在输出树中被隔开):

  包含空格的文本节点是在XSLT处理器执行之前将被去除的而且结果不显示在提交的HTML文档中的空白字符节点的一个例子。现在查看一下middle-initial和last元素的xsl:value-of表达式两者中的文本节点:

.

  既然文本节点包含了一个非空白字符(句号),那么它将被XSLT处理器保留起来。幸运的是XSLT提供了一个专门的元素,xsl:text,它能够避免这个问题。xsl:text元素在文本节点中明确地保留空白。下面的例子在两个xsl:value-of元素之间保留了一个空格。

  尽管XSLT默认方式下从源文档中去除掉空白字符节点,但它也提供一种方法去改变这种默认做法。你可以使用xsl:preserve-space去详细指出源文档中哪一种元素不应该被去除空白。例如,下面的转换详细指定了源文档中的story、poem和song元素不应该被去除掉。


   ...

  元素属性采用一个包含QName和”*”的名字检验的单个空白字符(white space-separated)列表。当你首先想在源文档中保留一些例外的空白时,XSLT也提供和 xsl:preserve-space一起使用的xsl:strip-space。参看下面的例子:




   ...

  既然这样,转换仅仅去除了author和title元素中的空白字符节点而保留其他地方的空白。除了这些XSLT技术之外,XML1.0还为作者提供一种在一个特殊的元素上下文中请求空白保留的方法。这通过全局的xml:space属性是很容易实现的,就像这样使用:

 ... 
  XSLT处理器在源文档中考虑这个属性是必需的,允许源文档的作者指出空白字符保留是否重要。
 
来源 的 期刊,可通过当地新闻组或其它更好方式获得,
下载本文示例代码
阅读(996) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~