在消息赋值中使用非规范化 XPath

如果使用 .Net 消息部分,则可以用 XML 序列化属性批注代码,不过,当代码中还附带可分辨字段和/或属性批注时,会使 XPath 表达式变得极其复杂。 这些复杂的 XPath 表达式可能是非规范化的。 非规范化 XPath 只能用于直接绑定的业务流程,如果用于逻辑绑定或物理绑定的业务流程,可能会失败。 直接绑定的业务流程不依赖管道来处理 XML 文档,因此在处理之前,整个 XML 文档已加载到内存中。

规范和非规范 XPath

XPath 的规范或缩写形式使用 XPath 规范 (http://www.w3.org/TR/xpath) 中的缩写语法来指定位置路径。 下面是规范化 XPath 表达式的一些判别属性:

  • child::默认情况下,表达式的每个步骤都假定轴

  • @ 是 的 attribute::缩写。

  • // 是 的 /descendant-or-self::node()/缩写。

  • . 是 的 self::node()缩写。

  • .. 是 的 parent::node()缩写。

    规范 XPath 表达式是简单的表达式,例如 /*[local-name()='element-name' and namespaceURI()='http://MyUri.org']/*[local-name()='element-name']/@*[local-name='attribute-name']

    这与非规范化形式的 XPath 相反。 此形式也称为“常规形式”或“任意 XPath”,由任意复杂且可能组合多个轴的表达式进行区分: //element-name//*[local-name()='element-name' and position()=2]

示例

以下面的程序为例:

using System;
using System.IO;
using System.Xml.Serialization;
using Microsoft.XLANGs.BaseTypes;

namespace ComplexNetXPath
{
    public class Animal
    {
        [Property( typeof(BTS.RetryCount) )]
        public int NumberOfLegs;
    }
    public class Snake : Animal
    {
        public Snake()
        {
            NumberOfLegs = 0;
        }
    }
    public class Dog : Animal
    {
        public Dog()
        {
            NumberOfLegs = 4;
        }
    }
    public class Zoo
    {
        //
        // Dogs and snakes are the possible animals of
        // the week.
        //
        [XmlElement(typeof(Snake))]
        [XmlElement(typeof(Dog))]
        public Animal AnimalOfTheWeek;
    }
    class Class1
    {
        static void Main(string[] args)
        {
            XmlSerializer ser = new XmlSerializer(typeof(Zoo));
            Stream s = Console.OpenStandardOutput();
            Zoo z = new Zoo();
            z.AnimalOfTheWeek = new Dog();
            ser.Serialize( s, z );
            s.Flush();
            Console.WriteLine("------------------");
            z.AnimalOfTheWeek = new Snake();
            ser.Serialize( s, z );
            s.Flush();
        }
    }
}

Zoo 类型包含一个 Animal 字段,它可以是 Snake 或 Dog。 Animal 实例有一个 NumberOfLegs 字段,用 PropertyAttribute 进行批注,将 BTS.RetryCount 属性分配给此字段。

注意

实际的应用程序要定义自己的属性。

当本周动物是 Dog 时,序列化的 Zoo 实例如下所示:

<Zoo>
  <Dog>
    <NumberOfLegs>4</NumberOfLegs>
  </Dog>
</Zoo>

当本周动物是 Snake 时,序列化的 Zoo 实例如下所示:

<Zoo>
  <Snake>
    <NumberOfLegs>0</NumberOfLegs>
  </Snake>
</Zoo>

以与 .Net Zoo 类等价的 XML 架构为例,用于选择 RetryCount 属性的 XPath 表达式将允许 Snake 或 Dog 步骤显示在该属性的路径中:

/*[local-name()='Zoo' and namespace-uri()='']/*[(local-name()='Dog' and namespace-uri()='') or (local-name()='Snake' and namespace-uri()='')]/*[local-name()='NumberOfLegs' and namespace-uri()='']

XML 管道组件无法处理这种非规范化 XPath 表达式。 为了避免这种情况,请不要将多选择 XML 序列化属性与 XML 管道一起使用,在使用以下 XML 序列化属性时也应谨慎:

  • XmlElementAttribute

  • XmlAttributeAttribute

  • XmlArrayItemAttribute