Utilizzo di Xpath non canonici nelle assegnazioni messaggio
Se si utilizzano parti di messaggio .NET, è possibile commentare il codice con l'attributo di serializzazione XML che, se accompagnato anche da campi differenzianti e/o annotazioni di proprietà, può dar luogo a espressioni XPath alquanto complesse. È possibile che queste espressioni XPath complesse siano espressioni non canoniche. Le espressioni XPath non canoniche devono essere utilizzate solo nelle orchestrazioni con binding diretto e possono generare errori con orchestrazioni con binding logico o fisico. Le orchestrazioni con binding diretto non si avvalgono di una pipeline per l'elaborazione del documento XML, pertanto viene caricato in memoria l'intero documento prima dell'elaborazione.
Espressioni XPath canoniche e non canoniche
La forma canonica o breve di XPath usa la sintassi abbreviata dalla specifica XPath (http://www.w3.org/TR/xpath) per specificare un percorso di posizione. Di seguito sono riportate alcune delle proprietà specifiche delle espressioni XPath:
L'asse
child::
viene assunto per impostazione predefinita per ogni passaggio dell'espressione@
è breve perattribute::
.//
è breve per/descendant-or-self::node()/
..
è breve perself::node()
...
è breve perparent::node()
.Le espressioni XPath canoniche sono espressioni semplici,
/*[local-name()='element-name' and namespaceURI()='http://MyUri.org']/*[local-name()='element-name']/@*[local-name='attribute-name']
ad esempio .Questa espressione può essere confrontata con la forma canonica di XPath. Questo modulo è noto anche come "forma generale" o "XPath arbitrario" ed è distinto da espressioni che sono arbitrariamente complesse e possono combinare più assi:
//element-name//*[local-name()='element-name' and position()=2]
.
Esempio
Considerare il programma riportato di seguito:
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();
}
}
}
Il tipo Zoo contiene un campo Animal il cui valore può essere Snake o Dog. L'istanza Animal presenta un campo NumberOfLegs annotato con PropertyAttribute che assegna la proprietà BTS.RetryCount a questo campo.
Nota
Un'applicazione reale definirebbe le proprie proprietà.
Quando l'animale della settimana è un cane, l'istanza Zoo serializzata è:
<Zoo>
<Dog>
<NumberOfLegs>4</NumberOfLegs>
</Dog>
</Zoo>
Quando l'animale della settimana è un serpente, l'istanza Zoo serializzata è:
<Zoo>
<Snake>
<NumberOfLegs>0</NumberOfLegs>
</Snake>
</Zoo>
Considerando l'XML Schema equivalente alla classe .NET Zoo, l'espressione XPath per la selezione della proprietà RetryCount consentirebbe la presenza di un passaggio Snake o Dog nel percorso della proprietà:
/*[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()='']
I componenti della pipeline XML non possono gestire questa espressione XPath non canonica. Per prevenire questa situazione, è necessario evitare di utilizzare attributi di serializzazione XML a scelta multipla insieme alle pipeline XML e prestare attenzione quando si utilizzano gli attributi di serializzazione XML seguenti:
XmlElementAttribute
XmlAttributeAttribute
XmlArrayItemAttribute