Internet Engineering Task Force (IETF)                          N. Freed
Request for Comments: 5784                                      S. Vedam
Category: Standards Track                               Sun Microsystems
ISSN: 2070-1721                                               March 2010
        
Internet Engineering Task Force (IETF)                          N. Freed
Request for Comments: 5784                                      S. Vedam
Category: Standards Track                               Sun Microsystems
ISSN: 2070-1721                                               March 2010
        

Sieve Email Filtering: Sieves and Display Directives in XML

筛选电子邮件筛选:筛选和显示XML中的指令

Abstract

摘要

This document describes a way to represent Sieve email filtering language scripts in XML. Representing Sieves in XML is intended not as an alternate storage format for Sieve but rather as a means to facilitate manipulation of scripts using XML tools.

本文档描述了一种用XML表示电子邮件过滤语言脚本的方法。用XML表示Sieves并不是Sieve的一种替代存储格式,而是一种使用XML工具简化脚本操作的方法。

The XML representation also defines additional elements that have no counterparts in the regular Sieve language. These elements are intended for use by graphical user interfaces and provide facilities for labeling or grouping sections of a script so they can be displayed more conveniently. These elements are represented as specially structured comments in regular Sieve format.

XML表示还定义了在常规筛语言中没有对应项的其他元素。这些元素旨在供图形用户界面使用,并提供用于标记或分组脚本部分的工具,以便更方便地显示它们。这些元素以常规格式表示为特殊结构的注释。

Status of This Memo

关于下段备忘

This is an Internet Standards Track document.

这是一份互联网标准跟踪文件。

This document is a product of the Internet Engineering Task Force (IETF). It represents the consensus of the IETF community. It has received public review and has been approved for publication by the Internet Engineering Steering Group (IESG). Further information on Internet Standards is available in Section 2 of RFC 5741.

本文件是互联网工程任务组(IETF)的产品。它代表了IETF社区的共识。它已经接受了公众审查,并已被互联网工程指导小组(IESG)批准出版。有关互联网标准的更多信息,请参见RFC 5741第2节。

Information about the current status of this document, any errata, and how to provide feedback on it may be obtained at http://www.rfc-editor.org/info/rfc5784.

有关本文件当前状态、任何勘误表以及如何提供反馈的信息,请访问http://www.rfc-editor.org/info/rfc5784.

Copyright Notice

版权公告

Copyright (c) 2010 IETF Trust and the persons identified as the document authors. All rights reserved.

版权所有(c)2010 IETF信托基金和确定为文件作者的人员。版权所有。

This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (http://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Simplified BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Simplified BSD License.

本文件受BCP 78和IETF信托有关IETF文件的法律规定的约束(http://trustee.ietf.org/license-info)自本文件出版之日起生效。请仔细阅读这些文件,因为它们描述了您对本文件的权利和限制。从本文件中提取的代码组件必须包括信托法律条款第4.e节中所述的简化BSD许可证文本,并提供简化BSD许可证中所述的无担保。

Table of Contents

目录

   1.  Introduction . . . . . . . . . . . . . . . . . . . . . . . . .  3
   2.  Conventions Used in This Document  . . . . . . . . . . . . . .  4
   3.  Grammatical Structure of Sieve . . . . . . . . . . . . . . . .  4
   4.  XML Representation of Sieve  . . . . . . . . . . . . . . . . .  6
     4.1.  XML Display Directives . . . . . . . . . . . . . . . . . .  9
     4.2.  Structured Comments  . . . . . . . . . . . . . . . . . . . 10
     4.3.  Validation . . . . . . . . . . . . . . . . . . . . . . . . 11
   5.  Security Considerations  . . . . . . . . . . . . . . . . . . . 11
   6.  IANA Considerations  . . . . . . . . . . . . . . . . . . . . . 11
   7.  References . . . . . . . . . . . . . . . . . . . . . . . . . . 12
     7.1.  Normative References . . . . . . . . . . . . . . . . . . . 12
     7.2.  Informative References . . . . . . . . . . . . . . . . . . 13
   Appendix A.  Extended Example  . . . . . . . . . . . . . . . . . . 14
   Appendix B.  XML Schema for Sieves in XML  . . . . . . . . . . . . 21
   Appendix C.  Relax NG Schema for Sieves in XML . . . . . . . . . . 24
   Appendix D.  Stylesheet for Conversion from XML  . . . . . . . . . 26
   Appendix E.  Acknowledgements  . . . . . . . . . . . . . . . . . . 32
        
   1.  Introduction . . . . . . . . . . . . . . . . . . . . . . . . .  3
   2.  Conventions Used in This Document  . . . . . . . . . . . . . .  4
   3.  Grammatical Structure of Sieve . . . . . . . . . . . . . . . .  4
   4.  XML Representation of Sieve  . . . . . . . . . . . . . . . . .  6
     4.1.  XML Display Directives . . . . . . . . . . . . . . . . . .  9
     4.2.  Structured Comments  . . . . . . . . . . . . . . . . . . . 10
     4.3.  Validation . . . . . . . . . . . . . . . . . . . . . . . . 11
   5.  Security Considerations  . . . . . . . . . . . . . . . . . . . 11
   6.  IANA Considerations  . . . . . . . . . . . . . . . . . . . . . 11
   7.  References . . . . . . . . . . . . . . . . . . . . . . . . . . 12
     7.1.  Normative References . . . . . . . . . . . . . . . . . . . 12
     7.2.  Informative References . . . . . . . . . . . . . . . . . . 13
   Appendix A.  Extended Example  . . . . . . . . . . . . . . . . . . 14
   Appendix B.  XML Schema for Sieves in XML  . . . . . . . . . . . . 21
   Appendix C.  Relax NG Schema for Sieves in XML . . . . . . . . . . 24
   Appendix D.  Stylesheet for Conversion from XML  . . . . . . . . . 26
   Appendix E.  Acknowledgements  . . . . . . . . . . . . . . . . . . 32
        
1. Introduction
1. 介绍

Sieve [RFC5228] is a language for filtering email messages at or around the time of final delivery. It is designed to be implementable on either a mail client or mail server. It is meant to be extensible, simple, and independent of access protocol, mail architecture, and operating system, and it is intended to be manipulated by a variety of different user interfaces.

Sieve[RFC5228]是一种用于在最终交付时或前后过滤电子邮件的语言。它被设计为可以在邮件客户端或邮件服务器上实现。它具有可扩展性、简单性,并且独立于访问协议、邮件体系结构和操作系统,并且可以由各种不同的用户界面进行操作。

Some user interface environments have extensive existing facilities for manipulating material represented in XML [XML]. While adding support for alternate data syntaxes may be possible in most if not all of these environments, it may not be particularly convenient to do so. The obvious way to deal with this issue is to map Sieves into XML, possibly on a separate back-end system, manipulate the XML, and convert it back to normal Sieve format.

一些用户界面环境具有广泛的现有设施,可用于操作以XML[XML]表示的材料。虽然在大多数(如果不是所有的话)环境中都可以添加对备用数据语法的支持,但这样做可能不是特别方便。处理这个问题的明显方法是将筛映射为XML,可能在单独的后端系统上,操作XML,并将其转换回正常的筛格式。

The fact that conversion into and out of XML may be done as a separate operation on a different system argues strongly for defining a common XML representation for Sieve. This way, different front-end user interfaces can be used with different back-end mapping and storage facilities.

XML的转换和转换可以作为不同系统上的一个单独操作来完成,这一事实有力地证明了为Sieve定义通用XML表示的必要性。这样,不同的前端用户界面可以与不同的后端映射和存储设施一起使用。

Another issue with the creation and manipulation of Sieve scripts by user interfaces is that the language is strictly focused on describing email filtering operations. The language contains no mechanisms for indicating how a given script should be presented in a user interface. Such information can be represented in XML very easily, so it makes sense to define a framework to do this as part of the XML format. A structured comment convention is then used to retain this information when the script is converted to normal Sieve format.

通过用户界面创建和操作筛选脚本的另一个问题是,该语言严格侧重于描述电子邮件过滤操作。该语言不包含指示给定脚本应如何在用户界面中显示的机制。这样的信息可以很容易地用XML表示,因此定义一个框架作为XML格式的一部分是有意义的。然后,当脚本转换为标准格式时,使用结构化注释约定来保留此信息。

It should be noted, however, that the ability for different front ends to use the same mapping and storage facilities does not mean that the additional XML information produced by different front ends will interoperate.

但是,应该注意的是,不同前端使用相同映射和存储设施的能力并不意味着由不同前端生成的附加XML信息可以互操作。

Various Sieve extensions have already been defined, e.g., [RFC5183], [RFC5229], [RFC5230], [RFC5231], [RFC5232], [RFC5233], [RFC5235], [RFC5293], and more are planned. The set of extensions available varies from one implementation to the next and may even change as a result of configuration choices. It is therefore essential that the XML representation of Sieve be able to accommodate Sieve extensions without requiring schema changes. It is also desirable that Sieve extensions not require changes to the code that converts to and from the XML representation.

已经定义了各种筛网扩展,例如,[RFC5183]、[RFC5229]、[RFC5230]、[RFC5231]、[RFC5232]、[RFC5233]、[RFC5235]、[RFC5293],并计划更多。可用的扩展集因实现的不同而不同,甚至可能因配置选择而改变。因此,Sieve的XML表示必须能够适应Sieve扩展,而不需要更改模式。筛扩展不需要更改与XML表示之间的转换代码,这也是可取的。

This specification defines an XML representation for Sieve scripts and explains how the conversion process to and from XML works. The XML representation is capable of accommodating any future Sieve extension as long as the underlying Sieve grammar remains unchanged. Furthermore, code that converts from XML to the normal Sieve format requires no changes to accommodate extensions, while code used to convert from normal Sieve format to XML only requires changes when new control commands are added -- a rare event. An XML Schema, Relax NG Schema, and a sample stylesheet to convert from XML format are also provided in the appendices.

本规范定义了筛选脚本的XML表示,并解释了与XML之间的转换过程是如何工作的。只要底层的Sieve语法保持不变,XML表示就能够适应任何未来的Sieve扩展。此外,从XML转换为普通筛格式的代码不需要更改以适应扩展,而用于从普通筛格式转换为XML的代码只需要在添加新的控制命令时进行更改——这是一个罕见的事件。附录中还提供了XML模式、RELAXNG模式和从XML格式转换的示例样式表。

2. Conventions Used in This Document
2. 本文件中使用的公约

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119 [RFC2119].

本文件中的关键词“必须”、“不得”、“要求”、“应”、“不应”、“应”、“不应”、“建议”、“可”和“可选”应按照RFC 2119[RFC2119]中所述进行解释。

The term "processor" is used throughout this document to refer to agents that convert Sieve to and from the XML representation. The term "editor" refers to agents that operate on, possibly creating or modifying, Sieves in XML format.

本文档中使用的术语“processor”是指在XML表示之间进行转换的代理。术语“编辑器”指的是在XML格式的筛子上操作(可能创建或修改)的代理。

3. Grammatical Structure of Sieve
3. 筛的语法结构

The Sieve language is designed to be highly extensible without making any changes to the basic language syntax. Accordingly, the syntax of Sieve, defined in Section 8 of [RFC5228], is entirely structural in nature and employs no reserved words of any sort.

Sieve语言设计为高度可扩展,而不需要对基本语言语法进行任何更改。因此,[RFC5228]第8节中定义的Sieve语法在本质上是完全结构化的,并且不使用任何类型的保留字。

Structurally, a Sieve script consists of a series of commands. Each command, in turn, consists of an identifier, zero or more arguments, an optional test or test-list, and finally an optional block containing another series of commands. Commands are further broken down into controls and actions, although this distinction cannot be determined from the grammar.

从结构上讲,筛选脚本由一系列命令组成。每个命令依次由标识符、零个或多个参数、可选测试或测试列表以及最后一个包含另一系列命令的可选块组成。命令被进一步分解为控件和操作,尽管这种区别不能从语法上确定。

Some example Sieve controls are:

一些示例筛控制包括:

   stop;               <-- No arguments, test, or command block
   require "fileinto"; <-- Control with a single argument
   if true {stop;}     <-- Control with test and command block
        
   stop;               <-- No arguments, test, or command block
   require "fileinto"; <-- Control with a single argument
   if true {stop;}     <-- Control with test and command block
        

Some examples of Sieve actions are:

筛分作用的一些示例如下:

discard;            <-- Action with no arguments, test, or command block
fileinto "folder";  <-- Action with an argument
        
discard;            <-- Action with no arguments, test, or command block
fileinto "folder";  <-- Action with an argument
        

At the time of this writing, there are no controls defined that accept both arguments and a test. Similarly, there are currently no defined actions that allow either a test or a command block. Nevertheless, the Sieve grammar allows such constructs to be defined by some future extension.

在撰写本文时,没有定义同时接受参数和测试的控件。类似地,目前还没有允许测试或命令块的已定义操作。然而,Sieve语法允许通过将来的扩展来定义这样的结构。

A test consists of an identifier followed by zero or more arguments, then another test or test-list. Unlike commands, tests cannot be followed by a command block.

一个测试包括一个标识符,后跟零个或多个参数,然后是另一个测试或测试列表。与命令不同,测试后不能有命令块。

Here are some examples of Sieve tests. Note that such tests have to appear as part of a command in order to be syntactically valid:

下面是一些筛分测试的例子。请注意,此类测试必须作为命令的一部分出现,以便在语法上有效:

   true                <-- Test with no argument or subordinate test
   envelope "to" "me@example.com" <-- Test with several arguments
   header :is "from" "you@example.com" <-- Test with tagged argument
        
   true                <-- Test with no argument or subordinate test
   envelope "to" "me@example.com" <-- Test with several arguments
   header :is "from" "you@example.com" <-- Test with tagged argument
        

Command or test arguments can be either string lists, whole numbers, or tags. (Tags are simply identifiers preceded by a colon.) Note that although the Sieve grammar treats single strings as a degenerate case of a string list, some tests or actions have arguments that can only be individual strings, not lists.

命令或测试参数可以是字符串列表、整数或标记。(标记只是以冒号开头的标识符。)注意,尽管筛语法将单个字符串视为字符串列表的退化情况,但某些测试或操作的参数只能是单个字符串,不能是列表。

Here is an example showing the use of both a test-list and a string list:

下面的示例显示了测试列表和字符串列表的用法:

   if anyof (not exists ["From", "Date"],
             header :contains "from" "fool@example.edu") {
     discard;
   }
        
   if anyof (not exists ["From", "Date"],
             header :contains "from" "fool@example.edu") {
     discard;
   }
        

Extensions can add new controls, actions, tests, or arguments to existing controls or actions. Extensions have also changed how string content is interpreted, although this is not relevant to this specification. However, it is especially important to note that so far, only one of the many defined Sieve extensions -- the foreverypart extension [RFC5703] -- has added new controls to the language. It seems safe to assume that, due to their nature, future addition of controls will be relatively rare.

扩展可以向现有控件或操作添加新控件、操作、测试或参数。扩展还改变了字符串内容的解释方式,尽管这与本规范无关。然而,需要特别注意的是,到目前为止,在众多定义的筛扩展中,只有一个(foreverypart扩展[RFC5703])向该语言添加了新控件。似乎可以安全地假设,由于其性质,未来增加的控制措施将相对较少。

Finally, comments are allowed between lexical elements in a Sieve script. One important use case for comments is encoding meta-data about the script, a facility that is lacking in the Sieve language. Therefore, comments need to be preserved in the XML representation.

最后,允许在筛选脚本中的词汇元素之间添加注释。注释的一个重要用例是对脚本的元数据进行编码,这是Sieve语言中缺少的一种功能。因此,注释需要保留在XML表示中。

4. XML Representation of Sieve
4. Sieve的XML表示

Sieve controls and actions are represented in XML as "control" or "action" elements, respectively. The command's identifier appears as a name attribute on the element itself. This is the only attribute allowed on controls and actions -- arguments, tests, test-lists, and nested command blocks are all represented as nested elements. While naming the element after the control or action itself may seem like a better choice, doing so would result in extensions requiring frequent corresponding schema changes.

筛选控件和操作在XML中分别表示为“control”或“action”元素。命令的标识符在元素本身上显示为名称属性。这是控件和操作上唯一允许的属性——参数、测试、测试列表和嵌套命令块都表示为嵌套元素。虽然以控件或操作本身命名元素似乎是更好的选择,但这样做会导致扩展需要频繁地更改相应的模式。

The example Sieve controls shown in the previous section would be represented as these XML fragments:

上一节中显示的示例筛控件将表示为以下XML片段:

    <control name="stop"/>
        
    <control name="stop"/>
        
    <control name="require"><str>fileinto</str></control>
        
    <control name="require"><str>fileinto</str></control>
        
    <control name="if">
     <test name="true"/><control name="stop"/>
    </control>
        
    <control name="if">
     <test name="true"/><control name="stop"/>
    </control>
        

The example Sieve actions shown above would appear in XML as:

上面显示的示例筛动作将以XML形式显示为:

   <action name="discard"/>
   <action name="fileinto"><str>folder</str></action>
        
   <action name="discard"/>
   <action name="fileinto"><str>folder</str></action>
        

The separation of controls from actions in the XML representation means that conversion from normal Sieve format to XML has to be able to distinguish between controls and actions. This is easily done by maintaining a list of all known controls since experience indicates new controls are rarely added. At the time of this writing, the list of defined controls consists of:

在XML表示中,控件与操作的分离意味着从标准筛格式到XML的转换必须能够区分控件和操作。这很容易通过维护所有已知控件的列表来实现,因为经验表明很少添加新控件。在撰写本文时,已定义控件的列表包括:

1. if [RFC5228],

1. 如果[RFC5228],

2. stop [RFC5228],

2. 停止[RFC5228],

3. require [RFC5228],

3. 需要[RFC5228],

4. foreverypart [RFC5703], and

4. 永久部分[RFC5703],以及

5. break [RFC5703].

5. 中断[RFC5703]。

It should be noted that with this approach unknown controls will simply be treated as actions and can be passed back and forth between the two representations. The treatment of a control as an action is

应该注意的是,使用这种方法,未知控件将被简单地视为操作,并且可以在两种表示之间来回传递。将控件作为操作进行处理是非常必要的

unlikely to cause other issues since knowledge of a control's language semantics is almost always required to take advantage of it.

不太可能导致其他问题,因为利用控件几乎总是需要了解控件的语言语义。

Tests are represented in the same basic way as controls and actions, that is, as a "test" element with a name attribute giving the test identifier. For example, the following XML fragments show various types of tests:

测试以与控件和操作相同的基本方式表示,即作为一个“test”元素,其name属性提供测试标识符。例如,以下XML片段显示了各种类型的测试:

   <test name="true"/>
        
   <test name="true"/>
        
   <test name="envelope"/>
     <str>to</str><str>me@example.com</str>
   </test>
        
   <test name="envelope"/>
     <str>to</str><str>me@example.com</str>
   </test>
        
   <test name="header"/>
     <tag>is</tag><str>from</str><str>you@example.com</str>
   </test>
        
   <test name="header"/>
     <tag>is</tag><str>from</str><str>you@example.com</str>
   </test>
        

String, number, and tag arguments are represented as "str", "num", and "tag" elements, respectively. The actual string, number, or tag identifier appears as text inside the element. None of these elements have any defined attributes. Several examples of arguments have already appeared in the preceding control, action, and test examples. Any whitespace in the str body content MUST be preserved by the processor. Also, note that since strings and tags are represented as element text, any quotes or other syntactic elements required in the regular Sieve representation are dropped rather than being carried over into the XML.

字符串、数字和标记参数分别表示为“str”、“num”和“tag”元素。实际的字符串、数字或标记标识符在元素中显示为文本。这些元素都没有任何已定义的属性。前面的控件、操作和测试示例中已经出现了几个参数示例。处理器必须保留str正文内容中的任何空白。另外,请注意,由于字符串和标记被表示为元素文本,因此在常规的Sieve表示中所需的任何引号或其他语法元素都会被删除,而不会被带入XML中。

String list arguments are represented as a "list" element, which in turn contains one or more str elements. Note that this allows the distinction between a single string and a string list containing a single string to be preserved. This is not essential since a list containing a single string could simply be mapped to a string, but it seems prudent to maintain the distinction when mapping to and from XML.

字符串列表参数表示为“list”元素,该元素又包含一个或多个str元素。请注意,这允许保留单个字符串和包含单个字符串的字符串列表之间的区别。这不是必需的,因为包含单个字符串的列表可以简单地映射到字符串,但在映射到XML和从XML映射时,保持这种区别似乎是谨慎的。

Nested command blocks appear as a series of control or action elements inside of an outer control or action element. No block element is needed since an inner command block can only appear once and only after any arguments, tests, or test-lists. For example:

嵌套命令块显示为外部控件或操作元素内部的一系列控件或操作元素。不需要块元素,因为内部命令块只能在任何参数、测试或测试列表之后出现一次。例如:

   <control name="if">
     <test name="anyof">
       <test name="not">
         <test name="exists">
           <list><str>From</str><str>Date</str></list>
         </test>
       </test>
       <test name="header">
         <tag>contains</tag>
         <str>from</str>
         <str>fool@example.edu</str>
       </test>
     </test>
     <action name="discard"/>
   </control>
        
   <control name="if">
     <test name="anyof">
       <test name="not">
         <test name="exists">
           <list><str>From</str><str>Date</str></list>
         </test>
       </test>
       <test name="header">
         <tag>contains</tag>
         <str>from</str>
         <str>fool@example.edu</str>
       </test>
     </test>
     <action name="discard"/>
   </control>
        

Sieve comments are mapped to a special "comment" element in XML. Both hash and bracketed comments are mapped to the same construct so the distinction between the two is lost in XML. XML comments are not used because some XML tools do not make it convenient to access comment nodes.

筛注释映射到XML中的一个特殊“comment”元素。散列和括号内的注释都映射到同一个构造,因此两者之间的区别在XML中丢失。不使用XML注释,因为某些XML工具不便于访问注释节点。

Comments are allowed between commands and inside "test" elements. But comments aren't allowed directly inside commands -- due to limitations of XML Schema, special enclosing "preamble" and "postamble" elements are needed:

命令之间和“测试”元素内部允许有注释。但命令中不允许直接使用注释——由于XML模式的限制,需要使用特殊的封闭“preamble”和“postmble”元素:

   <control name="if">
     <preamble>
       <comment>Check to see if message should be discarded</comment>
     </preamble>
     <test name="anyof">
       <test name="not">
         <test name="exists">
           <list><str>From</str><str>Date</str></list>
         </test>
       </test>
       <test name="header">
         <tag>contains</tag>
         <str>from</str>
         <str>fool@example.edu</str>
       </test>
     </test>
     <action name="discard"/>
     <postamble>
       <comment>End of discard check</comment>
     </postamble>
   </control>
        
   <control name="if">
     <preamble>
       <comment>Check to see if message should be discarded</comment>
     </preamble>
     <test name="anyof">
       <test name="not">
         <test name="exists">
           <list><str>From</str><str>Date</str></list>
         </test>
       </test>
       <test name="header">
         <tag>contains</tag>
         <str>from</str>
         <str>fool@example.edu</str>
       </test>
     </test>
     <action name="discard"/>
     <postamble>
       <comment>End of discard check</comment>
     </postamble>
   </control>
        
4.1. XML Display Directives
4.1. XML显示指令

Sometimes graphical user interfaces are a convenient way to provide Sieve management functions to users. These interfaces typically summarize/annotate/group/display Sieve script(s) in an intuitive way for end users.

有时,图形用户界面是向用户提供筛选管理功能的一种方便方式。这些界面通常以直观的方式为最终用户总结/注释/分组/显示筛选脚本。

To do this effectively, the graphical user interface may require additional information about the Sieve script itself. That information or "meta-data" might include, but is not limited to, a Sieve name (identifying the current Sieve), whether the Sieve is enabled or disabled, and the order in which the parts of the Sieve are presented to the user. The graphical user interface may also choose to provide mechanisms to allow the user to modify the script.

为了有效地做到这一点,图形用户界面可能需要有关Sieve脚本本身的附加信息。该信息或“元数据”可能包括但不限于筛子名称(识别当前筛子)、筛子是启用还是禁用以及筛子各部分呈现给用户的顺序。图形用户界面还可以选择提供允许用户修改脚本的机制。

It is often useful for a graphical user interface to group related Sieve script elements and provide an interface that displays these groups separately so they can be managed as a single object. Some examples include Sieve statements that together provide vacation responders, blacklists/whitelists, and other types of filtering controls.

对于图形用户界面来说,将相关的脚本元素分组并提供一个单独显示这些组的界面通常很有用,这样就可以将它们作为单个对象进行管理。一些示例包括Sieve语句,它们一起提供休假响应者、黑名单/白名单和其他类型的过滤控件。

Some advanced graphical user interfaces may even provide a natural language representation of a Sieve script and/or an advanced interface to present Sieve statements directly to the user.

一些高级图形用户界面甚至可以提供筛选脚本的自然语言表示和/或高级界面,以直接向用户呈现筛选语句。

A graphical user interface may also choose to support only a subset of action commands in the Sieve language (and its extensions), and so a mechanism to indicate the extent of support and characterize the relationships between those supported action commands and the test (with its arguments) is immensely useful and probably required for clients that may not have complete knowledge of Sieve grammar and semantics.

图形用户界面也可以选择仅支持筛语言(及其扩展)中的一部分操作命令,因此可以选择一种机制来指示支持范围,并描述这些支持的操作命令与测试(及其参数)之间的关系非常有用,对于可能不完全了解语法和语义的客户可能需要。

The Sieve language contains no mechanisms for indicating how a given script should be presented in a user interface. The language also does not contain any specific mechanisms to represent other sorts of meta-data about the script. Providing support for such meta-data as part of a Sieve script is currently totally implementation specific and is usually done by imposing some type of structure on comments.

Sieve语言不包含指示给定脚本应如何在用户界面中显示的机制。该语言也不包含任何特定的机制来表示关于脚本的其他种类的元数据。作为Sieve脚本的一部分提供对此类元数据的支持目前完全是特定于实现的,通常通过在注释上施加某种类型的结构来实现。

However, such information can be represented in XML very easily, so it makes sense to define a framework to do this as part of the XML format. Implementations MAY choose to use structured comments to retain this information when the script is converted to normal Sieve format.

然而,这样的信息可以很容易地用XML表示,因此定义一个框架来作为XML格式的一部分是有意义的。当脚本转换为标准格式时,实现可以选择使用结构化注释来保留此信息。

The sample schemata for the XML representation of Sieve allows XML in foreign namespaces to be inserted in the same places "comment" elements can appear in Sieve scripts. This is the preferred means of including additional information. Alternately, the schema defines two display directives -- displayblock and displaydata -- as containers for meta-data needed by graphical user interfaces.

Sieve的XML表示的示例模式允许将外部名称空间中的XML插入到Sieve脚本中“comment”元素可能出现的相同位置。这是包含附加信息的首选方法。或者,模式定义两个显示指令——displayblock和displaydata——作为图形用户界面所需元数据的容器。

Editors MAY use displayblock, displaydata, and foreign namespaces to associate meta-data. Some editors find it inconvenient to preserve this additional data during an editing session. Editors MAY preserve this data during an editing session for compatibility with other editors.

编辑器可以使用displayblock、displaydata和外部名称空间来关联元数据。一些编辑器发现在编辑会话期间保存这些附加数据很不方便。编辑器可以在编辑会话期间保留此数据,以与其他编辑器兼容。

The displayblock element can be used to enclose any number of Sieve statements at any level. It is semantically meaningless to the Sieve script itself. It allows an arbitrary set of attributes. Implementations MAY use this to provide many simple, display-related meta-data for the Sieve such as Sieve identifier, group identifier, order of processing, etc.

displayblock元素可用于在任何级别封装任意数量的Sieve语句。它在语义上对Sieve脚本本身没有意义。它允许一组任意属性。实现可以使用它为筛子提供许多简单的、显示相关的元数据,例如筛子标识符、组标识符、处理顺序等。

The displaydata element supports any number of arbitrary child elements. Implementations MAY use this to represent complex data about that Sieve such as a natural language representation of Sieve or a way to provide the Sieve script directly.

displaydata元素支持任意数量的子元素。实现可以使用它来表示有关该筛的复杂数据,例如筛的自然语言表示或直接提供筛脚本的方法。

4.2. Structured Comments
4.2. 结构化评论

Since the XML representation is not intended as a storage format, there needs to be a way to preserve the additional information that can be included in the XML representation in the normal Sieve syntax. This is done through the use of three structured comment conventions:

由于XML表示不打算用作存储格式,因此需要有一种方法以正常语法保存XML表示中可以包含的附加信息。这是通过使用三种结构化注释约定完成的:

1. XML content in other namespaces is placed in Sieve bracketed comments beginning with the string "/* [/" and ending with the string "/] */".

1. 其他名称空间中的XML内容放在括号内的注释中,以字符串“/*[/”开头,以字符串“/]*/”结尾。

2. The content of displaydata elements is placed in Sieve bracketed comments beginning with the string "/* [|" and ending with the string "|] */".

2. displaydata元素的内容放在括号内的注释中,以字符串“/*[|”开头,以字符串“|]*/”结尾。

3. The beginning of a displayblock element is mapped to a bracketed Sieve comment beginning with the string "/* [*", which then lists any displayblock attribute names and values in XML format. The end of a displayblock element is mapped to a comment of the form "*] */".

3. displayblock元素的开头映射到以字符串“/*[*”开头的括号内的筛选注释,该字符串以XML格式列出任何displayblock属性名称和值。displayblock元素的结尾映射到格式为“*]*/”的注释。

Processors MUST preserve the additional information allowed in the XML format and SHOULD use the structured comment format shown above.

处理者必须保留XML格式中允许的附加信息,并应使用上述结构化注释格式。

Note: If "*/" is found in the XML content, when mapped into a comment, it would prematurely terminate that comment. Escaping this sequence would often be inconvenient for processors. Editors SHALL NOT include "*/" within displayblock, displaydata, or foreign markup. Processors MAY regard documents containing "*/" in foreign markup, displayblock, or displaydata as invalid.

注意:如果在XML内容中找到“*/”,当映射到注释时,它将提前终止该注释。转义此序列通常会给处理器带来不便。编辑器不得在displayblock、displaydata或外部标记中包含“*/”。处理者可能认为在外部标记、displayblock或displaydata中包含“*/”的文档无效。

4.3. Validation
4.3. 验证

A processor MAY validate documents against a schema, and it MAY reject any that do not conform. For any document that a processor does not reject as invalid, any markup that the processor cannot understand by reference to this specification MAY be discarded.

处理器可以根据模式验证文档,也可以拒绝任何不符合模式的文档。对于处理者不认为无效而拒绝的任何文档,处理者通过引用本规范无法理解的任何标记都可能被丢弃。

Note that example Relax NG and XML Schema are given in the appendices below.

请注意,下面的附录中给出了RELAXNG和XML模式示例。

5. Security Considerations
5. 安全考虑

Any syntactically valid Sieve script can be represented in XML. Accordingly, all security considerations applicable to Sieve and any extensions used also apply to the XML representation.

任何语法上有效的Sieve脚本都可以用XML表示。因此,适用于Sieve的所有安全注意事项以及使用的任何扩展也适用于XML表示。

The use of XML carries its own security risks. Section 7 of RFC 3470 [RFC3470] discusses these risks.

XML的使用有其自身的安全风险。RFC 3470[RFC3470]第7节讨论了这些风险。

It is axiomatic that a Sieve editor must be trusted to do what the user specifies. If XML formats are used, this trust necessarily must extend to the components involved in converting to and from XML format.

这是不言而喻的,必须信任筛选编辑器来执行用户指定的操作。如果使用XML格式,这种信任必须扩展到与XML格式进行转换所涉及的组件。

Arbitrary data can be included using other namespaces or placed in the extensible displayblock and displaydata constructs defined in this specification, possibly including entire scripts and other executable content in languages other than Sieve. Such material will necessarily have its own security considerations, which are beyond the scope of this document.

可以使用其他名称空间包含任意数据,也可以将任意数据放置在本规范中定义的可扩展displayblock和displaydata结构中,可能包括整个脚本和其他非Sieve语言的可执行内容。此类材料必须有其自身的安全考虑因素,这超出了本文件的范围。

6. IANA Considerations
6. IANA考虑

This section registers a new XML namespace per the procedures in RFC 3688 [RFC3688].

本节根据RFC 3688[RFC3688]中的过程注册一个新的XML命名空间。

   URI:  urn:ietf:params:xml:ns:sieve
        
   URI:  urn:ietf:params:xml:ns:sieve
        
   Registrant Contact:  IETF Sieve working group
                        <ietf-mta-filters@imc.org>
        
   Registrant Contact:  IETF Sieve working group
                        <ietf-mta-filters@imc.org>
        

XML:

XML:

     BEGIN
     <?xml version="1.0"?>
     <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.0//EN"
       "http://www.w3.org/TR/xhtml-basic/xhtml-basic10.dtd">
     <html xmlns="http://www.w3.org/1999/xhtml">
     <head>
       <meta http-equiv="content-type"
             content="text/html;charset=iso-8859-1"/>
       <title>Sieve Namespace</title>
     </head>
     <body>
       <h1>Namespace for Sieve Language objects expressed in XML</h1>
       <h2>urn:ietf:params:xml:ns:sieve</h2>
       <p>See <a href="http://www.rfc-editor.org/rfc/rfc5784.txt">
        RFC 5784</a>.
       </p>
     </body>
     </html>
     END
        
     BEGIN
     <?xml version="1.0"?>
     <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.0//EN"
       "http://www.w3.org/TR/xhtml-basic/xhtml-basic10.dtd">
     <html xmlns="http://www.w3.org/1999/xhtml">
     <head>
       <meta http-equiv="content-type"
             content="text/html;charset=iso-8859-1"/>
       <title>Sieve Namespace</title>
     </head>
     <body>
       <h1>Namespace for Sieve Language objects expressed in XML</h1>
       <h2>urn:ietf:params:xml:ns:sieve</h2>
       <p>See <a href="http://www.rfc-editor.org/rfc/rfc5784.txt">
        RFC 5784</a>.
       </p>
     </body>
     </html>
     END
        
7. References
7. 工具书类
7.1. Normative References
7.1. 规范性引用文件

[OASISRNC] Clark, J., "RELAX NG Compact Syntax", OASIS Committee Specification rnc, November 2002.

[OASISNC]Clark,J.,“RELAXNG紧凑语法”,OASIS委员会规范rnc,2002年11月。

[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, March 1997.

[RFC2119]Bradner,S.,“RFC中用于表示需求水平的关键词”,BCP 14,RFC 2119,1997年3月。

[RFC3470] Hollenbeck, S., Rose, M., and L. Masinter, "Guidelines for the Use of Extensible Markup Language (XML) within IETF Protocols", BCP 70, RFC 3470, January 2003.

[RFC3470]Hollenbeck,S.,Rose,M.,和L.Masinter,“IETF协议中可扩展标记语言(XML)的使用指南”,BCP 70,RFC 3470,2003年1月。

[RFC3688] Mealling, M., "The IETF XML Registry", BCP 81, RFC 3688, January 2004.

[RFC3688]Mealling,M.“IETF XML注册表”,BCP 81,RFC 3688,2004年1月。

[RFC5228] Guenther, P. and T. Showalter, "Sieve: An Email Filtering Language", RFC 5228, January 2008.

[RFC5228]Guenther,P.和T.Showalter,“筛选:电子邮件过滤语言”,RFC 5228,2008年1月。

[XML] Bray, T., Paoli, J., Sperberg-McQueen, C., Maler, E., and F. Yergeau, "Extensible Markup Language (XML) 1.0 (Fifth Edition)", W3C REC-xml-20081126, November 2008, <http://www.w3.org/TR/2008/REC-xml-20081126/>.

[XML]Bray,T.,Paoli,J.,Sperberg McQueen,C.,Maler,E.,和F.Yergeau,“可扩展标记语言(XML)1.0(第五版)”,W3C REC-XML-20081126,2008年11月<http://www.w3.org/TR/2008/REC-xml-20081126/>.

7.2. Informative References
7.2. 资料性引用

[RFC5183] Freed, N., "Sieve Email Filtering: Environment Extension", RFC 5183, May 2008.

[RFC5183]弗里德,N.,“筛选电子邮件过滤:环境扩展”,RFC 5183,2008年5月。

[RFC5229] Homme, K., "Sieve Email Filtering: Variables Extension", RFC 5229, January 2008.

[RFC5229]Homme,K.,“筛选电子邮件过滤:变量扩展”,RFC5292008年1月。

[RFC5230] Showalter, T. and N. Freed, "Sieve Email Filtering: Vacation Extension", RFC 5230, January 2008.

[RFC5230]Showalter,T.和N.Freed,“筛选电子邮件过滤:假期延长”,RFC 5230,2008年1月。

[RFC5231] Segmuller, W. and B. Leiba, "Sieve Email Filtering: Relational Extension", RFC 5231, January 2008.

[RFC5231]Segmuler,W.和B.Leiba,“筛选电子邮件过滤:关系扩展”,RFC 52312008年1月。

[RFC5232] Melnikov, A., "Sieve Email Filtering: Imap4flags Extension", RFC 5232, January 2008.

[RFC5232]Melnikov,A.,“筛选电子邮件过滤:Imap4flags扩展”,RFC 5232,2008年1月。

[RFC5233] Murchison, K., "Sieve Email Filtering: Subaddress Extension", RFC 5233, January 2008.

[RFC5233]Murchison,K.,“筛选电子邮件过滤:子地址扩展”,RFC 52332008年1月。

[RFC5235] Daboo, C., "Sieve Email Filtering: Spamtest and Virustest Extensions", RFC 5235, January 2008.

[RFC5235]Daboo,C.,“筛选电子邮件过滤:垃圾邮件测试和病毒测试扩展”,RFC5352008年1月。

[RFC5293] Degener, J. and P. Guenther, "Sieve Email Filtering: Editheader Extension", RFC 5293, August 2008.

[RFC5293]Degener,J.和P.Guenther,“筛选电子邮件过滤:Editheader扩展”,RFC 5293,2008年8月。

[RFC5703] Hansen, T. and C. Daboo, "Sieve Email Filtering: MIME Part Tests, Iteration, Extraction, Replacement, and Enclosure", RFC 5703, October 2009.

[RFC5703]Hansen,T.和C.Daboo,“筛选电子邮件过滤:MIME部分测试、迭代、提取、替换和封装”,RFC 57032009年10月。

Appendix A. Extended Example
附录A.扩展示例

The example Sieve script given in Section 9 of [RFC5228] would be represented in XML as the following code component:

[RFC5228]第9节中给出的示例筛脚本将用XML表示为以下代码组件:

   <sieve xmlns="urn:ietf:params:xml:ns:sieve">
     <comment>
       Example Sieve Filter
       Declare any optional features or extensions used by the script
     </comment>
        
   <sieve xmlns="urn:ietf:params:xml:ns:sieve">
     <comment>
       Example Sieve Filter
       Declare any optional features or extensions used by the script
     </comment>
        
     <control name="require">
       <str>fileinto</str>
     </control>
     <comment>
       Handle messages from known mailing lists.
       Move messages from IETF filter discussion list to filter mailbox.
     </comment>
     <control name="if">
       <test name="header">
         <tag>is</tag>
         <str>Sender</str>
         <str>owner-ietf-mta-filters@imc.org</str>
       </test>
       <action name="fileinto">
         <str>filter</str>
       </action>
       <postamble>
         <comment>move to "filter" mailbox</comment>
       </postamble>
     </control>
        
     <control name="require">
       <str>fileinto</str>
     </control>
     <comment>
       Handle messages from known mailing lists.
       Move messages from IETF filter discussion list to filter mailbox.
     </comment>
     <control name="if">
       <test name="header">
         <tag>is</tag>
         <str>Sender</str>
         <str>owner-ietf-mta-filters@imc.org</str>
       </test>
       <action name="fileinto">
         <str>filter</str>
       </action>
       <postamble>
         <comment>move to "filter" mailbox</comment>
       </postamble>
     </control>
        
     <comment>
       Keep all messages to or from people in my company.
     </comment>
     <control name="elsif">
       <test name="address">
         <tag>domain</tag>
         <tag>is</tag>
         <list>
           <str>From</str>
           <str>To</str>
         </list>
         <str>example.com</str>
       </test>
       <action name="keep"/>
     </control>
        
     <comment>
       Keep all messages to or from people in my company.
     </comment>
     <control name="elsif">
       <test name="address">
         <tag>domain</tag>
         <tag>is</tag>
         <list>
           <str>From</str>
           <str>To</str>
         </list>
         <str>example.com</str>
       </test>
       <action name="keep"/>
     </control>
        
     <comment>
       Try and catch unsolicited email.  If a message is not to me,
       or it contains a subject known to be spam, file it away.
     </comment>
     <control name="elsif">
       <test name="anyof">
         <test name="not">
           <test name="address">
             <tag>all</tag>
             <tag>contains</tag>
             <list>
               <str>To</str>
               <str>Cc</str>
               <str>Bcc</str>
             </list>
             <str>me@example.com</str>
           </test>
         </test>
         <test name="header">
           <tag>matches</tag>
           <str>subject</str>
           <list>
             <str>*make*money*fast*</str>
             <str>*university*dipl*mas*</str>
           </list>
         </test>
       </test>
       <action name="fileinto">
         <str>spam</str>
       </action>
     </control>
     <control name="else">
       <preamble>
         <comment>
           Move all other (non-company) mail to "personal"
           mailbox.
         </comment>
       </preamble>
       <action name="fileinto">
         <str>personal</str>
       </action>
     </control>
        
     <comment>
       Try and catch unsolicited email.  If a message is not to me,
       or it contains a subject known to be spam, file it away.
     </comment>
     <control name="elsif">
       <test name="anyof">
         <test name="not">
           <test name="address">
             <tag>all</tag>
             <tag>contains</tag>
             <list>
               <str>To</str>
               <str>Cc</str>
               <str>Bcc</str>
             </list>
             <str>me@example.com</str>
           </test>
         </test>
         <test name="header">
           <tag>matches</tag>
           <str>subject</str>
           <list>
             <str>*make*money*fast*</str>
             <str>*university*dipl*mas*</str>
           </list>
         </test>
       </test>
       <action name="fileinto">
         <str>spam</str>
       </action>
     </control>
     <control name="else">
       <preamble>
         <comment>
           Move all other (non-company) mail to "personal"
           mailbox.
         </comment>
       </preamble>
       <action name="fileinto">
         <str>personal</str>
       </action>
     </control>
        
   </sieve>
        
   </sieve>
        

The same script could be annotated with graphical display hints in a variety of ways. Three possible code components that do this are:

同一脚本可以通过多种方式用图形显示提示进行注释。执行此操作的三个可能代码组件是:

   <sieve xmlns="urn:ietf:params:xml:ns:sieve">
        
   <sieve xmlns="urn:ietf:params:xml:ns:sieve">
        
     <control name="require">
       <str>fileinto</str>
     </control>
        
     <control name="require">
       <str>fileinto</str>
     </control>
        
     <displayblock name="File filter list mail" order="1"
                   group="FILE_TO_FOLDER" enable="true">
       <control name="if">
         <test name="header">
           <tag>is</tag>
           <str>Sender</str>
           <str>owner-ietf-mta-filters@imc.org</str>
         </test>
         <action name="fileinto">
           <str>filter</str>
         </action>
       </control>
     </displayblock>
        
     <displayblock name="File filter list mail" order="1"
                   group="FILE_TO_FOLDER" enable="true">
       <control name="if">
         <test name="header">
           <tag>is</tag>
           <str>Sender</str>
           <str>owner-ietf-mta-filters@imc.org</str>
         </test>
         <action name="fileinto">
           <str>filter</str>
         </action>
       </control>
     </displayblock>
        
     <displayblock name="Keep all company mail" order="2"
                   group="KEEP_MESSAGE" enable="true">
       <control name="elsif">
         <test name="address">
           <tag>domain</tag>
           <tag>is</tag>
           <list>
             <str>From</str>
             <str>To</str>
           </list>
           <str>example.com</str>
         </test>
         <action name="keep"/>
      </control>
     </displayblock>
        
     <displayblock name="Keep all company mail" order="2"
                   group="KEEP_MESSAGE" enable="true">
       <control name="elsif">
         <test name="address">
           <tag>domain</tag>
           <tag>is</tag>
           <list>
             <str>From</str>
             <str>To</str>
           </list>
           <str>example.com</str>
         </test>
         <action name="keep"/>
      </control>
     </displayblock>
        
     <displayblock name="File suspected spam" order="3"
                   group="FILE_TO_FOLDER" enable="true">
        <control name="elsif">
          <test name="anyof">
            <test name="not">
              <test name="address">
                <tag>all</tag>
                <tag>contains</tag>
                <list>
        
     <displayblock name="File suspected spam" order="3"
                   group="FILE_TO_FOLDER" enable="true">
        <control name="elsif">
          <test name="anyof">
            <test name="not">
              <test name="address">
                <tag>all</tag>
                <tag>contains</tag>
                <list>
        
                  <str>To</str>
                  <str>Cc</str>
                  <str>Bcc</str>
                </list>
                <str>me@example.com</str>
              </test>
            </test>
            <test name="header">
              <tag>matches</tag>
              <str>subject</str>
              <list>
                <str>*make*money*fast*</str>
                <str>*university*dipl*mas*</str>
              </list>
            </test>
          </test>
          <action name="fileinto">
            <str>spam</str>
          </action>
        </control>
      </displayblock>
        
                  <str>To</str>
                  <str>Cc</str>
                  <str>Bcc</str>
                </list>
                <str>me@example.com</str>
              </test>
            </test>
            <test name="header">
              <tag>matches</tag>
              <str>subject</str>
              <list>
                <str>*make*money*fast*</str>
                <str>*university*dipl*mas*</str>
              </list>
            </test>
          </test>
          <action name="fileinto">
            <str>spam</str>
          </action>
        </control>
      </displayblock>
        
     <displayblock name="File noncompany mail as personal" order="4"
                   group="FILE_TO_FOLDER" enable="true">
       <control name="else">
         <action name="fileinto">
           <str>personal</str>
         </action>
       </control>
     </displayblock>
        
     <displayblock name="File noncompany mail as personal" order="4"
                   group="FILE_TO_FOLDER" enable="true">
       <control name="else">
         <action name="fileinto">
           <str>personal</str>
         </action>
       </control>
     </displayblock>
        
   </sieve>
        
   </sieve>
        

Note that since displayblock elements are semantically null as far as the script itself is concerned, they can be used to group structures like elsif and else that are tied to statements in other groups.

请注意,因为就脚本本身而言,displayblock元素在语义上是空的,所以它们可以用于分组结构,如elsif和其他组中绑定到语句的else。

The representation of this script in regular Sieve syntax uses structured comments:

此脚本的常规语法表示使用结构化注释:

   require "fileinto";
   /* [* name="File filter list mail" order="1"
         group="FILE_TO_FOLDER" enable="true" */
   if header :is "Sender" "owner-ietf-mta-filters@imc.org"
   {
     fileinto "filter";
   }
   /* *] */
   /* [* name="Keep all company mail" order="2"
         group="KEEP_MESSAGE" enable="true" */
   elsif address :domain :is [ "From", "To" ] "example.com"
   {
     keep;
   }
   /* *] */
   /* [* name="File suspected spam" order="3"
         group="FILE_TO_FOLDER" enable="true" */
   elsif anyof ( not ( address :all :contains [ "To", "Cc", "Bcc" ]
                       "me@example.com" ),
                 header :matches "subject" [ "*make*money*fast*",
                                             "*university*dipl*mas*" ] )
   {
     fileinto "spam";
   }
   /* *] */
   /* [* name="File noncompany mail as personal" order="4"
         group="FILE_TO_FOLDER" enable="true" */
   else
   {
     fileinto "personal";
   }
   /* *] */
        
   require "fileinto";
   /* [* name="File filter list mail" order="1"
         group="FILE_TO_FOLDER" enable="true" */
   if header :is "Sender" "owner-ietf-mta-filters@imc.org"
   {
     fileinto "filter";
   }
   /* *] */
   /* [* name="Keep all company mail" order="2"
         group="KEEP_MESSAGE" enable="true" */
   elsif address :domain :is [ "From", "To" ] "example.com"
   {
     keep;
   }
   /* *] */
   /* [* name="File suspected spam" order="3"
         group="FILE_TO_FOLDER" enable="true" */
   elsif anyof ( not ( address :all :contains [ "To", "Cc", "Bcc" ]
                       "me@example.com" ),
                 header :matches "subject" [ "*make*money*fast*",
                                             "*university*dipl*mas*" ] )
   {
     fileinto "spam";
   }
   /* *] */
   /* [* name="File noncompany mail as personal" order="4"
         group="FILE_TO_FOLDER" enable="true" */
   else
   {
     fileinto "personal";
   }
   /* *] */
        

A separate namespace can be used to embed text or structured information:

可以使用单独的命名空间嵌入文本或结构化信息:

   <sieve xmlns="urn:ietf:params:xml:ns:sieve"
          xmlns:nls="http://example.com/nls">
        
   <sieve xmlns="urn:ietf:params:xml:ns:sieve"
          xmlns:nls="http://example.com/nls">
        

<nls:interpretation> If the email header "Sender" is owner-ietf-mta-filters@imc.org, then file it into the "filter" folder.

<nls:EXPLATION>如果电子邮件标题“发件人”是所有者ietf mta-filters@imc.org,然后将其归档到“过滤器”文件夹中。

Otherwise, if the address in the "From" or "To" has a domain that is "example.com", then keep it.

否则,如果“发件人”或“收件人”中的地址的域为“example.com”,则保留该域。

Otherwise, messages meeting with any of these conditions:

否则,符合以下任何条件的消息:

(1) None of the addresses in "To", "Cc", or "Bcc" contain the domain "example.com".

(1) “收件人”、“抄送”或“密件抄送”中的地址均不包含域“example.com”。

(2) The "Subject" field matches the pattern *make*money*fast* or *university*dipl*mas*, then file it into the "spam" folder.

(2) “主题”字段匹配模式*赚钱*快速*或*大学*dipl*mas*,然后将其归档到“垃圾邮件”文件夹中。

If all else fails, then file the message in the "personal" folder. </nls:interpretation>

如果所有其他操作都失败,则将邮件归档到“个人”文件夹中</nls:口译>

... the actual Sieve script ...

... 实际的筛选脚本。。。

   </sieve>
        
   </sieve>
        

Alternately, displaydata elements can be used to accomplish the same thing:

或者,displaydata元素可用于完成相同的任务:

   <sieve xmlns="urn:ietf:params:xml:ns:sieve">
        
   <sieve xmlns="urn:ietf:params:xml:ns:sieve">
        

<displaydata> <nls-interpretation> If the email header "Sender" is owner-ietf-mta-filters@imc.org, then file it into the "filter" folder.

<displaydata><nls解释>,如果电子邮件标题“发件人”是所有者ietf mta-filters@imc.org,然后将其归档到“过滤器”文件夹中。

Otherwise, if the address in the "From" or "To" has a domain that is "example.com", then keep it.

否则,如果“发件人”或“收件人”中的地址的域为“example.com”,则保留该域。

Otherwise, messages meeting with any of these conditions:

否则,符合以下任何条件的消息:

(1) None of the addresses in "To","Cc", or "Bcc" contain the domain "example.com".

(1) “收件人”、“抄送”或“密件抄送”中的地址均不包含域“example.com”。

(2) The "Subject" field matches the pattern *make*money*fast* or *university*dipl*mas*, then file it into the "spam" folder.

(2) “主题”字段匹配模式*赚钱*快速*或*大学*dipl*mas*,然后将其归档到“垃圾邮件”文件夹中。

         If all else fails, then file the message in the "personal"
         folder.
       </nls-interpretation>
     </displaydata>
        
         If all else fails, then file the message in the "personal"
         folder.
       </nls-interpretation>
     </displaydata>
        

... the actual Sieve script ...

... 实际的筛选脚本。。。

   </sieve>
        
   </sieve>
        

Again, structured comments are used to represent this in regular Sieve syntax:

同样,结构化注释用于以常规语法表示这一点:

     /* [|
       <nls-interpretation>
         If the email header "Sender" is owner-ietf-mta-filters@imc.org,
         then file it into the "filter" folder.
        
     /* [|
       <nls-interpretation>
         If the email header "Sender" is owner-ietf-mta-filters@imc.org,
         then file it into the "filter" folder.
        

Otherwise, if the address in the "From" or "To" has a domain that is "example.com", then keep it.

否则,如果“发件人”或“收件人”中的地址的域为“example.com”,则保留该域。

Otherwise, messages meeting with any of these conditions:

否则,符合以下任何条件的消息:

(1) None of the addresses in "To","Cc", or "Bcc" contain the domain "example.com".

(1) “收件人”、“抄送”或“密件抄送”中的地址均不包含域“example.com”。

(2) The "Subject" field matches the pattern *make*money*fast* or *university*dipl*mas*, then file it into the "spam" folder.

(2) “主题”字段匹配模式*赚钱*快速*或*大学*dipl*mas*,然后将其归档到“垃圾邮件”文件夹中。

         If all else fails, then file the message in the "personal"
         folder.
       </nls-interpretation>
     |] */
        
         If all else fails, then file the message in the "personal"
         folder.
       </nls-interpretation>
     |] */
        

... the actual Sieve script ...

... 实际的筛选脚本。。。

Appendix B. XML Schema for Sieves in XML
附录B.XML中筛子的XML模式

This appendix is informative. The following code component is an XML Schema for the XML representation of Sieve scripts. Most of the elements employing a complex content model allow use of elements in other namespaces, subject to lax XML Schema validation rules. Additionally, displaydata elements can be used to encapsulate arbitrary XML content. Finally, displayblock elements can be used as a general-purpose grouping mechanism -- arbitrary attributes are allowed on displayblock elements.

本附录为资料性附录。下面的代码组件是用于筛脚本的XML表示的XML模式。大多数采用复杂内容模型的元素都允许在其他名称空间中使用元素,但要遵守宽松的XML模式验证规则。此外,displaydata元素可用于封装任意XML内容。最后,displayblock元素可以用作通用分组机制——displayblock元素上允许有任意属性。

   <?xml version="1.0" encoding="UTF-8"?>
        
   <?xml version="1.0" encoding="UTF-8"?>
        
   <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
               xmlns="urn:ietf:params:xml:ns:sieve"
               targetNamespace="urn:ietf:params:xml:ns:sieve">
        
   <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
               xmlns="urn:ietf:params:xml:ns:sieve"
               targetNamespace="urn:ietf:params:xml:ns:sieve">
        
     <xsd:element name="sieve">
       <xsd:complexType>
         <xsd:sequence>
           <xsd:choice maxOccurs="unbounded" minOccurs="0">
        
     <xsd:element name="sieve">
       <xsd:complexType>
         <xsd:sequence>
           <xsd:choice maxOccurs="unbounded" minOccurs="0">
        
             <xsd:element ref="control"/>
             <xsd:element ref="action"/>
             <xsd:element ref="displayblock"/>
             <xsd:element ref="displaydata"/>
             <xsd:element ref="comment"/>
             <xsd:any namespace="##other" processContents="lax"/>
           </xsd:choice>
         </xsd:sequence>
       </xsd:complexType>
     </xsd:element>
        
             <xsd:element ref="control"/>
             <xsd:element ref="action"/>
             <xsd:element ref="displayblock"/>
             <xsd:element ref="displaydata"/>
             <xsd:element ref="comment"/>
             <xsd:any namespace="##other" processContents="lax"/>
           </xsd:choice>
         </xsd:sequence>
       </xsd:complexType>
     </xsd:element>
        
     <xsd:element name="comment" type="xsd:string"/>
        
     <xsd:element name="comment" type="xsd:string"/>
        
     <xsd:complexType name="ambles">
       <xsd:choice minOccurs="0" maxOccurs="unbounded">
         <xsd:element ref="displaydata"/>
         <xsd:element ref="comment"/>
         <xsd:any namespace="##other" processContents="lax"/>
      </xsd:choice>
     </xsd:complexType>
        
     <xsd:complexType name="ambles">
       <xsd:choice minOccurs="0" maxOccurs="unbounded">
         <xsd:element ref="displaydata"/>
         <xsd:element ref="comment"/>
         <xsd:any namespace="##other" processContents="lax"/>
      </xsd:choice>
     </xsd:complexType>
        
     <xsd:element name="preamble" type="ambles"/>
     <xsd:element name="postamble" type="ambles"/>
        
     <xsd:element name="preamble" type="ambles"/>
     <xsd:element name="postamble" type="ambles"/>
        
     <xsd:complexType name="command">
       <xsd:sequence>
         <xsd:element ref="preamble" minOccurs="0" maxOccurs="1"/>
         <xsd:choice minOccurs="0" maxOccurs="unbounded">
           <xsd:element ref="str"/>
           <xsd:element ref="num"/>
           <xsd:element ref="list"/>
           <xsd:element ref="tag"/>
         </xsd:choice>
         <xsd:element ref="test" minOccurs="0" maxOccurs="1"/>
         <xsd:choice minOccurs="0" maxOccurs="unbounded">
           <xsd:element ref="control"/>
           <xsd:element ref="action"/>
           <xsd:element ref="displayblock"/>
         </xsd:choice>
         <xsd:element ref="postamble" minOccurs="0" maxOccurs="1"/>
       </xsd:sequence>
       <xsd:attribute use="required" name="name" type="identifier"/>
     </xsd:complexType>
        
     <xsd:complexType name="command">
       <xsd:sequence>
         <xsd:element ref="preamble" minOccurs="0" maxOccurs="1"/>
         <xsd:choice minOccurs="0" maxOccurs="unbounded">
           <xsd:element ref="str"/>
           <xsd:element ref="num"/>
           <xsd:element ref="list"/>
           <xsd:element ref="tag"/>
         </xsd:choice>
         <xsd:element ref="test" minOccurs="0" maxOccurs="1"/>
         <xsd:choice minOccurs="0" maxOccurs="unbounded">
           <xsd:element ref="control"/>
           <xsd:element ref="action"/>
           <xsd:element ref="displayblock"/>
         </xsd:choice>
         <xsd:element ref="postamble" minOccurs="0" maxOccurs="1"/>
       </xsd:sequence>
       <xsd:attribute use="required" name="name" type="identifier"/>
     </xsd:complexType>
        
     <xsd:element name="control" type="command"/>
     <xsd:element name="action" type="command"/>
        
     <xsd:element name="control" type="command"/>
     <xsd:element name="action" type="command"/>
        
     <xsd:element name="test">
        
     <xsd:element name="test">
        
       <xsd:complexType>
         <xsd:sequence>
           <xsd:choice minOccurs="0" maxOccurs="unbounded">
             <xsd:element ref="str"/>
             <xsd:element ref="num"/>
             <xsd:element ref="list"/>
             <xsd:element ref="tag"/>
             <xsd:element ref="displaydata"/>
             <xsd:element ref="comment"/>
             <xsd:any namespace="##other" processContents="lax"/>
           </xsd:choice>
           <xsd:element ref="test" minOccurs="0"
                        maxOccurs="unbounded"/>
         </xsd:sequence>
         <xsd:attribute use="required" name="name" type="identifier"/>
       </xsd:complexType>
     </xsd:element>
        
       <xsd:complexType>
         <xsd:sequence>
           <xsd:choice minOccurs="0" maxOccurs="unbounded">
             <xsd:element ref="str"/>
             <xsd:element ref="num"/>
             <xsd:element ref="list"/>
             <xsd:element ref="tag"/>
             <xsd:element ref="displaydata"/>
             <xsd:element ref="comment"/>
             <xsd:any namespace="##other" processContents="lax"/>
           </xsd:choice>
           <xsd:element ref="test" minOccurs="0"
                        maxOccurs="unbounded"/>
         </xsd:sequence>
         <xsd:attribute use="required" name="name" type="identifier"/>
       </xsd:complexType>
     </xsd:element>
        
     <xsd:element name="list">
       <xsd:complexType>
         <xsd:sequence>
           <xsd:element ref="str" minOccurs="1"
                        maxOccurs="unbounded"/>
         </xsd:sequence>
       </xsd:complexType>
     </xsd:element>
        
     <xsd:element name="list">
       <xsd:complexType>
         <xsd:sequence>
           <xsd:element ref="str" minOccurs="1"
                        maxOccurs="unbounded"/>
         </xsd:sequence>
       </xsd:complexType>
     </xsd:element>
        
     <xsd:element name="tag" type="identifier"/>
        
     <xsd:element name="tag" type="identifier"/>
        
     <xsd:element name="str" type="xsd:string"/>
        
     <xsd:element name="str" type="xsd:string"/>
        
     <xsd:element name="num" type="xsd:nonNegativeInteger"/>
        
     <xsd:element name="num" type="xsd:nonNegativeInteger"/>
        
     <xsd:simpleType name="identifier">
       <xsd:restriction base="xsd:token">
         <xsd:pattern value="[A-Za-z_][A-Za-z0-9_]*"/>
       </xsd:restriction>
     </xsd:simpleType>
        
     <xsd:simpleType name="identifier">
       <xsd:restriction base="xsd:token">
         <xsd:pattern value="[A-Za-z_][A-Za-z0-9_]*"/>
       </xsd:restriction>
     </xsd:simpleType>
        
     <xsd:element name="displayblock">
       <xsd:complexType>
         <xsd:sequence>
           <xsd:choice minOccurs="0" maxOccurs="unbounded">
             <xsd:element ref="control"/>
             <xsd:element ref="action"/>
             <xsd:element ref="displayblock"/>
             <xsd:element ref="displaydata"/>
             <xsd:element ref="comment"/>
        
     <xsd:element name="displayblock">
       <xsd:complexType>
         <xsd:sequence>
           <xsd:choice minOccurs="0" maxOccurs="unbounded">
             <xsd:element ref="control"/>
             <xsd:element ref="action"/>
             <xsd:element ref="displayblock"/>
             <xsd:element ref="displaydata"/>
             <xsd:element ref="comment"/>
        
             <xsd:any namespace="##other" processContents="lax"/>
           </xsd:choice>
         </xsd:sequence>
         <xsd:anyAttribute processContents="skip"/>
       </xsd:complexType>
     </xsd:element>
        
             <xsd:any namespace="##other" processContents="lax"/>
           </xsd:choice>
         </xsd:sequence>
         <xsd:anyAttribute processContents="skip"/>
       </xsd:complexType>
     </xsd:element>
        
     <xsd:element name="displaydata">
       <xsd:complexType>
         <xsd:sequence minOccurs="0" maxOccurs="unbounded">
           <xsd:any processContents="skip"/>
         </xsd:sequence>
       </xsd:complexType>
     </xsd:element>
        
     <xsd:element name="displaydata">
       <xsd:complexType>
         <xsd:sequence minOccurs="0" maxOccurs="unbounded">
           <xsd:any processContents="skip"/>
         </xsd:sequence>
       </xsd:complexType>
     </xsd:element>
        
   </xsd:schema>
        
   </xsd:schema>
        
Appendix C. Relax NG Schema for Sieves in XML
附录C.XML中筛子的RELAXNG模式

This appendix is informative. The following code component defines a Relax NG Schema using compact notation OASISRNC [OASISRNC] for the XML representation of Sieve scripts. Most of the elements employing a complex content model allow unrestricted use of elements in other namespaces. Additionally, displaydata elements can be used to encapsulate arbitrary XML content. Finally, displayblock elements can be used as a general-purpose grouping mechanism -- arbitrary attributes are allowed on displayblock elements.

本附录为资料性附录。下面的代码组件使用压缩符号OAISRNC[OAISRNC]定义了一个RELAXNG模式,用于筛选脚本的XML表示。大多数采用复杂内容模型的元素都允许在其他名称空间中不受限制地使用元素。此外,displaydata元素可用于封装任意XML内容。最后,displayblock元素可以用作通用分组机制——displayblock元素上允许有任意属性。

   namespace sieve = "urn:ietf:params:xml:ns:sieve"
        
   namespace sieve = "urn:ietf:params:xml:ns:sieve"
        
   start = element sieve:sieve { ( control | action | displayblock |
                                   displaydata | comment | ext )* }
        
   start = element sieve:sieve { ( control | action | displayblock |
                                   displaydata | comment | ext )* }
        
   comment = element sieve:comment { xsd:string }
        
   comment = element sieve:comment { xsd:string }
        

ambles = ( ( displaydata | comment | ext )* ), empty

ambles=((displaydata | comment | ext)*),空

   preamble = element sieve:preamble { ambles }
   postamble = element sieve:postamble { ambles }
        
   preamble = element sieve:preamble { ambles }
   postamble = element sieve:postamble { ambles }
        
   command =
      (
         attribute name {
           xsd:token {
        
   command =
      (
         attribute name {
           xsd:token {
        
             pattern = "[A-Za-z_][A-Za-z0-9_]*" } },
         preamble?,
         ( str | num | \list | tag )*,
         test?,
         ( control | action | displayblock)*,
         postamble?
      ),
      empty
        
             pattern = "[A-Za-z_][A-Za-z0-9_]*" } },
         preamble?,
         ( str | num | \list | tag )*,
         test?,
         ( control | action | displayblock)*,
         postamble?
      ),
      empty
        
   control = element sieve:control { command }
   action = element sieve:action { command }
        
   control = element sieve:control { command }
   action = element sieve:action { command }
        
   test =
      element sieve:test
      {
         attribute name {
           xsd:token {
             pattern = "[A-Za-z_][A-Za-z0-9_]*" } },
         ( str | num | \list | tag | comment | ext )*,
         test*
      }
        
   test =
      element sieve:test
      {
         attribute name {
           xsd:token {
             pattern = "[A-Za-z_][A-Za-z0-9_]*" } },
         ( str | num | \list | tag | comment | ext )*,
         test*
      }
        
   \list = element sieve:list { str+ }
        
   \list = element sieve:list { str+ }
        
   tag = element sieve:tag {
           xsd:token {
             pattern = "[A-Za-z_][A-Za-z0-9_]*" } }
        
   tag = element sieve:tag {
           xsd:token {
             pattern = "[A-Za-z_][A-Za-z0-9_]*" } }
        
   str = element sieve:str { xsd:string }
        
   str = element sieve:str { xsd:string }
        
   num = element sieve:num { xsd:nonNegativeInteger }
        
   num = element sieve:num { xsd:nonNegativeInteger }
        
   any = ( element * { any } | attribute * { text } | text )*
        
   any = ( element * { any } | attribute * { text } | text )*
        
   ext = element * - sieve:* { any }*
        
   ext = element * - sieve:* { any }*
        
   displayblock =
      element sieve:displayblock
      {
         ( control | action | displayblock |
           displaydata | comment | ext )*,
         attribute * { text }*
      }
        
   displayblock =
      element sieve:displayblock
      {
         ( control | action | displayblock |
           displaydata | comment | ext )*,
         attribute * { text }*
      }
        
   displaydata = element sieve:displaydata { any* }
        
   displaydata = element sieve:displaydata { any* }
        
Appendix D. Stylesheet for Conversion from XML
附录D.从XML转换的样式表

This appendix is informative. The following code component is a stylesheet that can be used to convert the Sieve in XML representation to regular Sieve format. Content in other namespaces, displaydata, and displayblock elements are converted to structured comments as appropriate.

本附录为资料性附录。下面的代码组件是一个样式表,可用于将XML表示的筛转换为常规筛格式。其他名称空间、displaydata和displayblock元素中的内容将根据需要转换为结构化注释。

   <?xml version="1.0" encoding="UTF-8"?>
        
   <?xml version="1.0" encoding="UTF-8"?>
        
   <!-- Convert Sieve in XML to standard Sieve syntax -->
        
   <!-- Convert Sieve in XML to standard Sieve syntax -->
        
   <xsl:stylesheet version="1.0"
                   xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                   xmlns:sieve="urn:ietf:params:xml:ns:sieve">
        
   <xsl:stylesheet version="1.0"
                   xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                   xmlns:sieve="urn:ietf:params:xml:ns:sieve">
        
     <xsl:output method="text" encoding="UTF-8"
                 media-type="application/sieve"/>
        
     <xsl:output method="text" encoding="UTF-8"
                 media-type="application/sieve"/>
        
     <!-- Only preserve whitespace in str elements -->
     <xsl:strip-space elements="*"/>
     <xsl:preserve-space elements="sieve:str"/>
        
     <!-- Only preserve whitespace in str elements -->
     <xsl:strip-space elements="*"/>
     <xsl:preserve-space elements="sieve:str"/>
        
     <!-- Match top level sieve node,
          start processing in sieve mode -->
        
     <!-- Match top level sieve node,
          start processing in sieve mode -->
        
     <xsl:template match="sieve:sieve">
       <xsl:apply-templates select="*" mode="sieve">
         <xsl:with-param name="prefix" select="''"/>
       </xsl:apply-templates>
     </xsl:template>
        
     <xsl:template match="sieve:sieve">
       <xsl:apply-templates select="*" mode="sieve">
         <xsl:with-param name="prefix" select="''"/>
       </xsl:apply-templates>
     </xsl:template>
        
     <!-- Routine to properly literalize quotes in Sieve strings -->
        
     <!-- Routine to properly literalize quotes in Sieve strings -->
        
     <xsl:template name="quote-string">
       <xsl:param name="str"/>
       <xsl:choose>
         <xsl:when test="not($str)"/>
         <xsl:when test="contains($str, '&quot;')">
           <xsl:call-template name="quote-string">
             <xsl:with-param name="str"
                select="substring-before($str, '&quot;')"/>
           </xsl:call-template>
           <xsl:text>\&quot;</xsl:text>
           <xsl:call-template name="quote-string">
             <xsl:with-param name="str"
                select="substring-after($str, '&quot;')"/>
           </xsl:call-template>
        
     <xsl:template name="quote-string">
       <xsl:param name="str"/>
       <xsl:choose>
         <xsl:when test="not($str)"/>
         <xsl:when test="contains($str, '&quot;')">
           <xsl:call-template name="quote-string">
             <xsl:with-param name="str"
                select="substring-before($str, '&quot;')"/>
           </xsl:call-template>
           <xsl:text>\&quot;</xsl:text>
           <xsl:call-template name="quote-string">
             <xsl:with-param name="str"
                select="substring-after($str, '&quot;')"/>
           </xsl:call-template>
        
         </xsl:when>
         <xsl:when test="contains($str, '\')">
           <xsl:call-template name="quote-string">
             <xsl:with-param name="str"
                select="substring-before($str, '\')"/>
           </xsl:call-template>
           <xsl:text>\\</xsl:text>
           <xsl:call-template name="quote-string">
             <xsl:with-param name="str"
                select="substring-after($str, '\')"/>
           </xsl:call-template>
         </xsl:when>
         <xsl:otherwise>
           <xsl:value-of select="$str"/>
         </xsl:otherwise>
       </xsl:choose>
     </xsl:template>
        
         </xsl:when>
         <xsl:when test="contains($str, '\')">
           <xsl:call-template name="quote-string">
             <xsl:with-param name="str"
                select="substring-before($str, '\')"/>
           </xsl:call-template>
           <xsl:text>\\</xsl:text>
           <xsl:call-template name="quote-string">
             <xsl:with-param name="str"
                select="substring-after($str, '\')"/>
           </xsl:call-template>
         </xsl:when>
         <xsl:otherwise>
           <xsl:value-of select="$str"/>
         </xsl:otherwise>
       </xsl:choose>
     </xsl:template>
        
     <!-- Sieve mode processing templates -->
        
     <!-- Sieve mode processing templates -->
        
     <xsl:template match="sieve:control|sieve:action" mode="sieve">
       <xsl:param name="prefix"/>
       <xsl:text xml:space="preserve">
   </xsl:text>
       <xsl:value-of select="$prefix"/>
       <xsl:value-of select="@name"/>
       <xsl:variable name="blockbegin"
               select="generate-id(sieve:control|sieve:action)"/>
       <xsl:for-each select="*">
         <xsl:choose>
           <xsl:when test="self::sieve:str|self::sieve:num|
                           self::sieve:list|self::sieve:tag|
                           self::sieve:test">
             <xsl:apply-templates select="." mode="sieve"/>
           </xsl:when>
           <xsl:when test="generate-id(.) = $blockbegin">
             <xsl:text xml:space="preserve">
   </xsl:text>
             <xsl:value-of select="$prefix"/>
             <xsl:text>{</xsl:text>
             <xsl:apply-templates select="." mode="sieve">
               <xsl:with-param name="prefix"
                  select="concat($prefix, '  ')"/>
             </xsl:apply-templates>
           </xsl:when>
           <xsl:otherwise>
             <xsl:apply-templates select="." mode="sieve">
               <xsl:with-param name="prefix"
        
     <xsl:template match="sieve:control|sieve:action" mode="sieve">
       <xsl:param name="prefix"/>
       <xsl:text xml:space="preserve">
   </xsl:text>
       <xsl:value-of select="$prefix"/>
       <xsl:value-of select="@name"/>
       <xsl:variable name="blockbegin"
               select="generate-id(sieve:control|sieve:action)"/>
       <xsl:for-each select="*">
         <xsl:choose>
           <xsl:when test="self::sieve:str|self::sieve:num|
                           self::sieve:list|self::sieve:tag|
                           self::sieve:test">
             <xsl:apply-templates select="." mode="sieve"/>
           </xsl:when>
           <xsl:when test="generate-id(.) = $blockbegin">
             <xsl:text xml:space="preserve">
   </xsl:text>
             <xsl:value-of select="$prefix"/>
             <xsl:text>{</xsl:text>
             <xsl:apply-templates select="." mode="sieve">
               <xsl:with-param name="prefix"
                  select="concat($prefix, '  ')"/>
             </xsl:apply-templates>
           </xsl:when>
           <xsl:otherwise>
             <xsl:apply-templates select="." mode="sieve">
               <xsl:with-param name="prefix"
        
                  select="concat($prefix, '  ')"/>
             </xsl:apply-templates>
           </xsl:otherwise>
         </xsl:choose>
       </xsl:for-each>
       <xsl:choose>
         <xsl:when test="count(sieve:control|sieve:action) &gt; 0">
           <xsl:text xml:space="preserve">
   </xsl:text>
           <xsl:value-of select="$prefix"/>
           <xsl:text>}</xsl:text>
         </xsl:when>
         <xsl:otherwise>
           <xsl:text>;</xsl:text>
         </xsl:otherwise>
       </xsl:choose>
     </xsl:template>
        
                  select="concat($prefix, '  ')"/>
             </xsl:apply-templates>
           </xsl:otherwise>
         </xsl:choose>
       </xsl:for-each>
       <xsl:choose>
         <xsl:when test="count(sieve:control|sieve:action) &gt; 0">
           <xsl:text xml:space="preserve">
   </xsl:text>
           <xsl:value-of select="$prefix"/>
           <xsl:text>}</xsl:text>
         </xsl:when>
         <xsl:otherwise>
           <xsl:text>;</xsl:text>
         </xsl:otherwise>
       </xsl:choose>
     </xsl:template>
        
     <xsl:template match="sieve:preamble|sieve:postamble" mode="sieve">
       <xsl:param name="prefix"/>
       <xsl:apply-templates mode="sieve">
         <xsl:with-param name="prefix" select="$prefix"/>
       </xsl:apply-templates>
     </xsl:template>
        
     <xsl:template match="sieve:preamble|sieve:postamble" mode="sieve">
       <xsl:param name="prefix"/>
       <xsl:apply-templates mode="sieve">
         <xsl:with-param name="prefix" select="$prefix"/>
       </xsl:apply-templates>
     </xsl:template>
        
     <xsl:template match="sieve:test" mode="sieve">
       <xsl:text xml:space="preserve"> </xsl:text>
       <xsl:value-of select="@name"/>
       <xsl:apply-templates select="*[not(self::sieve:test)]"
                            mode="sieve"/>
       <xsl:if test="count(descendant::sieve:test) &gt; 0">
         <xsl:text> (</xsl:text>
         <xsl:for-each select="sieve:test">
           <xsl:apply-templates select="." mode="sieve"/>
           <xsl:if test="count(following-sibling::sieve:test) &gt; 0">
             <xsl:text>,</xsl:text>
           </xsl:if>
         </xsl:for-each>
         <xsl:text> )</xsl:text>
       </xsl:if>
     </xsl:template>
        
     <xsl:template match="sieve:test" mode="sieve">
       <xsl:text xml:space="preserve"> </xsl:text>
       <xsl:value-of select="@name"/>
       <xsl:apply-templates select="*[not(self::sieve:test)]"
                            mode="sieve"/>
       <xsl:if test="count(descendant::sieve:test) &gt; 0">
         <xsl:text> (</xsl:text>
         <xsl:for-each select="sieve:test">
           <xsl:apply-templates select="." mode="sieve"/>
           <xsl:if test="count(following-sibling::sieve:test) &gt; 0">
             <xsl:text>,</xsl:text>
           </xsl:if>
         </xsl:for-each>
         <xsl:text> )</xsl:text>
       </xsl:if>
     </xsl:template>
        
     <xsl:template match="sieve:str" mode="sieve">
       <xsl:text> &quot;</xsl:text>
       <xsl:call-template name="quote-string">
         <xsl:with-param name="str" select="text()"/>
       </xsl:call-template>
       <xsl:text>&quot;</xsl:text>
        
     <xsl:template match="sieve:str" mode="sieve">
       <xsl:text> &quot;</xsl:text>
       <xsl:call-template name="quote-string">
         <xsl:with-param name="str" select="text()"/>
       </xsl:call-template>
       <xsl:text>&quot;</xsl:text>
        
     </xsl:template>
        
     </xsl:template>
        
     <xsl:template match="sieve:num" mode="sieve">
       <xsl:text xml:space="preserve"> </xsl:text>
       <!-- Use numeric suffixes when possible -->
       <xsl:choose>
         <xsl:when test="(number(text()) mod 1073741824) = 0">
           <xsl:value-of select="number(text()) div 1073741824"/>
           <xsl:text>G</xsl:text>
         </xsl:when>
         <xsl:when test="(number(text()) mod 1048576) = 0">
           <xsl:value-of select="number(text()) div 1048576"/>
           <xsl:text>M</xsl:text>
         </xsl:when>
         <xsl:when test="(number(text()) mod 1024) = 0">
           <xsl:value-of select="number(text()) div 1024"/>
           <xsl:text>K</xsl:text>
         </xsl:when>
         <xsl:otherwise>
           <xsl:value-of select="text()"/>
         </xsl:otherwise>
       </xsl:choose>
     </xsl:template>
        
     <xsl:template match="sieve:num" mode="sieve">
       <xsl:text xml:space="preserve"> </xsl:text>
       <!-- Use numeric suffixes when possible -->
       <xsl:choose>
         <xsl:when test="(number(text()) mod 1073741824) = 0">
           <xsl:value-of select="number(text()) div 1073741824"/>
           <xsl:text>G</xsl:text>
         </xsl:when>
         <xsl:when test="(number(text()) mod 1048576) = 0">
           <xsl:value-of select="number(text()) div 1048576"/>
           <xsl:text>M</xsl:text>
         </xsl:when>
         <xsl:when test="(number(text()) mod 1024) = 0">
           <xsl:value-of select="number(text()) div 1024"/>
           <xsl:text>K</xsl:text>
         </xsl:when>
         <xsl:otherwise>
           <xsl:value-of select="text()"/>
         </xsl:otherwise>
       </xsl:choose>
     </xsl:template>
        
     <xsl:template match="sieve:list" mode="sieve">
       <xsl:text> [</xsl:text>
       <xsl:for-each select="sieve:str">
         <xsl:apply-templates select="." mode="sieve"/>
         <xsl:if test="count(following-sibling::sieve:str) &gt; 0">
           <xsl:text>,</xsl:text>
         </xsl:if>
       </xsl:for-each>
       <xsl:text> ]</xsl:text>
     </xsl:template>
        
     <xsl:template match="sieve:list" mode="sieve">
       <xsl:text> [</xsl:text>
       <xsl:for-each select="sieve:str">
         <xsl:apply-templates select="." mode="sieve"/>
         <xsl:if test="count(following-sibling::sieve:str) &gt; 0">
           <xsl:text>,</xsl:text>
         </xsl:if>
       </xsl:for-each>
       <xsl:text> ]</xsl:text>
     </xsl:template>
        
     <xsl:template match="sieve:tag" mode="sieve">
       <xsl:text> :</xsl:text>
       <xsl:value-of select="text()"/>
     </xsl:template>
        
     <xsl:template match="sieve:tag" mode="sieve">
       <xsl:text> :</xsl:text>
       <xsl:value-of select="text()"/>
     </xsl:template>
        
     <xsl:template match="sieve:comment" mode="sieve">
       <xsl:param name="prefix"/>
       <xsl:text xml:space="preserve">
   </xsl:text>
       <xsl:value-of select="$prefix"/>
       <xsl:text>/*</xsl:text>
       <xsl:value-of select="."/>
       <xsl:value-of select="$prefix"/>
        
     <xsl:template match="sieve:comment" mode="sieve">
       <xsl:param name="prefix"/>
       <xsl:text xml:space="preserve">
   </xsl:text>
       <xsl:value-of select="$prefix"/>
       <xsl:text>/*</xsl:text>
       <xsl:value-of select="."/>
       <xsl:value-of select="$prefix"/>
        
       <xsl:text>*/</xsl:text>
     </xsl:template>
        
       <xsl:text>*/</xsl:text>
     </xsl:template>
        
     <!-- Convert display information into structured comments -->
        
     <!-- Convert display information into structured comments -->
        
     <xsl:template match="sieve:displayblock" mode="sieve">
       <xsl:param name="prefix"/>
       <xsl:text xml:space="preserve">
   </xsl:text>
       <xsl:value-of select="$prefix"/>
       <xsl:text>/* [*</xsl:text>
       <xsl:apply-templates select="@*" mode="copy"/>
       <xsl:text> */</xsl:text>
       <xsl:apply-templates select="*" mode="sieve">
         <xsl:with-param name="prefix" select="$prefix"/>
       </xsl:apply-templates>
       <xsl:text xml:space="preserve">
   </xsl:text>
       <xsl:value-of select="$prefix"/>
       <xsl:text>/* *] */</xsl:text>
     </xsl:template>
        
     <xsl:template match="sieve:displayblock" mode="sieve">
       <xsl:param name="prefix"/>
       <xsl:text xml:space="preserve">
   </xsl:text>
       <xsl:value-of select="$prefix"/>
       <xsl:text>/* [*</xsl:text>
       <xsl:apply-templates select="@*" mode="copy"/>
       <xsl:text> */</xsl:text>
       <xsl:apply-templates select="*" mode="sieve">
         <xsl:with-param name="prefix" select="$prefix"/>
       </xsl:apply-templates>
       <xsl:text xml:space="preserve">
   </xsl:text>
       <xsl:value-of select="$prefix"/>
       <xsl:text>/* *] */</xsl:text>
     </xsl:template>
        
     <xsl:template match="sieve:displaydata" mode="sieve">
       <xsl:param name="prefix"/>
       <xsl:text xml:space="preserve">
   </xsl:text>
       <xsl:value-of select="$prefix"/>
       <xsl:text>/* [|</xsl:text>
       <xsl:apply-templates mode="copy">
         <xsl:with-param name="prefix"
                         select="concat($prefix, '  ')"/>
       </xsl:apply-templates>
       <xsl:text xml:space="preserve">
   </xsl:text>
       <xsl:value-of select="$prefix"/>
       <xsl:text>   |] */</xsl:text>
     </xsl:template>
        
     <xsl:template match="sieve:displaydata" mode="sieve">
       <xsl:param name="prefix"/>
       <xsl:text xml:space="preserve">
   </xsl:text>
       <xsl:value-of select="$prefix"/>
       <xsl:text>/* [|</xsl:text>
       <xsl:apply-templates mode="copy">
         <xsl:with-param name="prefix"
                         select="concat($prefix, '  ')"/>
       </xsl:apply-templates>
       <xsl:text xml:space="preserve">
   </xsl:text>
       <xsl:value-of select="$prefix"/>
       <xsl:text>   |] */</xsl:text>
     </xsl:template>
        
     <!-- Copy unrecnognized nodes and their descendants -->
        
     <!-- Copy unrecnognized nodes and their descendants -->
        
     <xsl:template match="*" mode="sieve">
       <xsl:param name="prefix"/>
       <xsl:text xml:space="preserve">
   </xsl:text>
       <xsl:value-of select="$prefix"/>
       <xsl:text>/* [/</xsl:text>
       <xsl:apply-templates select="." mode="copy">
         <xsl:with-param name="prefix"
        
     <xsl:template match="*" mode="sieve">
       <xsl:param name="prefix"/>
       <xsl:text xml:space="preserve">
   </xsl:text>
       <xsl:value-of select="$prefix"/>
       <xsl:text>/* [/</xsl:text>
       <xsl:apply-templates select="." mode="copy">
         <xsl:with-param name="prefix"
        
                         select="concat($prefix, '  ')"/>
       </xsl:apply-templates>
       <xsl:text xml:space="preserve">
   </xsl:text>
       <xsl:value-of select="$prefix"/>
       <xsl:text>   /] */</xsl:text>
     </xsl:template>
        
                         select="concat($prefix, '  ')"/>
       </xsl:apply-templates>
       <xsl:text xml:space="preserve">
   </xsl:text>
       <xsl:value-of select="$prefix"/>
       <xsl:text>   /] */</xsl:text>
     </xsl:template>
        
     <!-- Copy mode processing templates -->
        
     <!-- Copy mode processing templates -->
        
     <xsl:template match="*[not(node())]" mode="copy">
       <xsl:param name="prefix"/>
       <xsl:text xml:space="preserve">
   </xsl:text>
       <xsl:value-of select="$prefix"/>
       <xsl:text>&lt;</xsl:text>
       <xsl:value-of select="name()"/>
       <xsl:apply-templates select="@*" mode="copy"/>
       <xsl:text>/&gt;</xsl:text>
     </xsl:template>
        
     <xsl:template match="*[not(node())]" mode="copy">
       <xsl:param name="prefix"/>
       <xsl:text xml:space="preserve">
   </xsl:text>
       <xsl:value-of select="$prefix"/>
       <xsl:text>&lt;</xsl:text>
       <xsl:value-of select="name()"/>
       <xsl:apply-templates select="@*" mode="copy"/>
       <xsl:text>/&gt;</xsl:text>
     </xsl:template>
        
     <xsl:template match="*[node()]" mode="copy">
       <xsl:param name="prefix"/>
       <xsl:text xml:space="preserve">
   </xsl:text>
       <xsl:value-of select="$prefix"/>
       <xsl:text>&lt;</xsl:text>
       <xsl:value-of select="name()"/>
       <xsl:apply-templates select="@*" mode="copy"/>
       <xsl:text>&gt;</xsl:text>
       <xsl:apply-templates mode="copy">
         <xsl:with-param name="prefix"
                         select="concat($prefix, '  ')"/>
       </xsl:apply-templates>
       <xsl:if test="*[last()][not(text())]">
         <xsl:text xml:space="preserve">
   </xsl:text>
         <xsl:value-of select="$prefix"/>
       </xsl:if>
       <xsl:text>&lt;/</xsl:text>
       <xsl:value-of select="name()"/>
       <xsl:text>&gt;</xsl:text>
     </xsl:template>
        
     <xsl:template match="*[node()]" mode="copy">
       <xsl:param name="prefix"/>
       <xsl:text xml:space="preserve">
   </xsl:text>
       <xsl:value-of select="$prefix"/>
       <xsl:text>&lt;</xsl:text>
       <xsl:value-of select="name()"/>
       <xsl:apply-templates select="@*" mode="copy"/>
       <xsl:text>&gt;</xsl:text>
       <xsl:apply-templates mode="copy">
         <xsl:with-param name="prefix"
                         select="concat($prefix, '  ')"/>
       </xsl:apply-templates>
       <xsl:if test="*[last()][not(text())]">
         <xsl:text xml:space="preserve">
   </xsl:text>
         <xsl:value-of select="$prefix"/>
       </xsl:if>
       <xsl:text>&lt;/</xsl:text>
       <xsl:value-of select="name()"/>
       <xsl:text>&gt;</xsl:text>
     </xsl:template>
        
     <xsl:template match="@*" mode="copy">
       <xsl:text> </xsl:text>
       <xsl:value-of select="name()"/>
       <xsl:text>="</xsl:text>
        
     <xsl:template match="@*" mode="copy">
       <xsl:text> </xsl:text>
       <xsl:value-of select="name()"/>
       <xsl:text>="</xsl:text>
        
       <xsl:value-of select="."/>
       <xsl:text>"</xsl:text>
     </xsl:template>
        
       <xsl:value-of select="."/>
       <xsl:text>"</xsl:text>
     </xsl:template>
        
   </xsl:stylesheet>
        
   </xsl:stylesheet>
        
Appendix E. Acknowledgements
附录E.确认书

The stylesheet copy mode code is loosely based on a sample code posted to the xsl-list list by Americo Albuquerque. Jari Arkko, Robert Burrell Donkin, Andrew McKeon, Alexey Melnikov, and Aaron Stone provided useful comments on the document.

样式表复制模式代码松散地基于Americo Albuquerque发布到xsl列表的示例代码。Jari Arkko、Robert Burrell Donkin、Andrew McKeon、Alexey Melnikov和Aaron Stone对该文件提供了有用的评论。

Authors' Addresses

作者地址

Ned Freed Sun Microsystems 800 Royal Oaks Monrovia, CA 91016-6347 USA

Ned Freed Sun Microsystems 800 Royal Oaks Monrovia,加利福尼亚州91016-6347美国

   Phone: +1 909 457 4293
   EMail: ned.freed@mrochek.com
        
   Phone: +1 909 457 4293
   EMail: ned.freed@mrochek.com
        

Srinivas Saisatish Vedam Sun Microsystems

Srinivas Saisatish Vedam太阳微系统公司

   Phone: +91 80669 27577
   EMail: Srinivas.Sv@Sun.COM
        
   Phone: +91 80669 27577
   EMail: Srinivas.Sv@Sun.COM