2010-03-16 14 views
10

Yardım et, Stackoverflow!XSLT ile .NET Extension Objects - bir koleksiyon üzerinde yineleme nasıl?

Bazı verileri okuyan ve e-posta gönderen basit bir .NET 3.5 konsol uygulamasına sahibim. Bir XSLT stil sayfasındaki e-posta biçimini temsil ediyorum, böylece uygulamayı yeniden derlemeye gerek kalmadan e-postanın ifadelerini kolayca değiştirebiliriz.

Biz dönüşümü uyguladığınızda XSLT veri iletmek için Uzatma Nesneleri kullanıyorsanız: -:

<p> 
    Dear <xsl:value-of select="EmailNotification:get_FullName()" />: 
</p> 

yukarıdaki eserleri

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl" 
    xmlns:EmailNotification="ext:EmailNotification"> 

bu şekilde, biz gibi ifadeler olabilir ince.

// purely an example structure 
public struct EmailNotification 
{ 
    public string FullName { get; set; } 
} 

// Somewhere in some method ... 

var notification = new Notification("John Smith"); 

// ... 

XsltArgumentList xslArgs = new XsltArgumentList(); 
xslArgs.AddExtensionObject("ext:EmailNotification", notification); 

// ... 

// The part where it breaks! (This is where we do the transformation) 
xslt.Transform(fakeXMLDocument.CreateNavigator(), xslArgs, XmlWriter.Create(transformedXMLString)); 

Yani, yukarıdaki tüm kod çalışır: Böyle kodu aracılığıyla (kısalık için ihmal bazı alakasız kodu) nesnesi iletir. Ancak, böyle bir şey yapabileceğini böylece biraz fantezi (her zaman beni mahveden) almak ve bir koleksiyon geçmek istedi:

<p>The following accounts need to be verified:</p> 
<xsl:for-each select="EmailNotification:get_SomeCollection()"> 
    <ul> 
     <li> 
      <xsl:value-of select="@SomeAttribute" /> 
     </li> 
    </ul> 
<xsl:for-each> 

Ben uzatma nesnesinde koleksiyonu geçmek ve dönüştürmeye teşebbüs, ben aşağıdaki hatayı alıyorum:. Ben de geçmek deneyin ne olursa olsun

"Extension function parameters or return values which have Clr type 'String[]' are not supported." 

veya Liste, veya IEnumerable veya

Yani, sorularım şunlardır:

  1. XSLT'ye bir koleksiyonda nasıl geçebilirim?

  2. xsl: for-each içinde xsl: value-of select = "" için ne koyarım?

Yapmak istediğim şey, imkansız mı?


Düzenleme: Aşağıda iki cevap gördükten sonra, Chris Hynes' kod aldı ve çok hafif benim ihtiyaçlarına göre değiştirilebilir. Çözüm aşağıdaki gibidir:

// extension object public struct EmailNotification { public List<String> StringsSetElsewhere { private get; set; } public XPathNavigator StringsNodeSet { get { XmlDocument xmlDoc = new XmlDocument(); XmlElement root = xmlDoc.CreateElement("Strings"); xmlDoc.AppendChild(root); foreach (var s in StringsSetElsewhere) { XmlElement element = xmlDoc.CreateElement("String"); element.InnerText = s; root.AppendChild(element); } return xmlDoc.CreateNavigator(); } } } 

Ve XSLT'de

...

<xsl:for-each select="EmailNotification:get_StringsNodeSet()//String"> 
    <ul> 
     <li> 
      <xsl:value-of select="." /> 
     </li> 
    </ul> 
</xsl:for-each> 

mükemmel çalıştı!

cevap

9

Her biri için XSLT, bir düğümün yinelenecek şekilde ayarlanmasını bekler; bir diziyi doğrudan C# kodunuzdan geri gönderemezsiniz. Bir XPathNodeIterator döndürmelisiniz.Böyle

şey:

public static XPathNodeIterator GetSomeCollection() 
{  
    XmlDocument xmlDoc = new XmlDocument(); 

    string[] stringsToReturn = new string[] { "String1", "String2", "String3" }; 

    XmlElement root = xmlDoc.CreateElement("Strings"); 

    xmlDoc.AppendChild(root); 

    foreach (string s in stringsToReturn) 
    { 
     XmlElement el = xmlDoc.CreateElement("String"); 

     el.InnerText = s; 

     root.AppendChild(el); 
    } 

    XPathNodeIterator xNodeIt = xmlDoc.CreateNavigator().Select("."); 

    return xNodeIt; 
} 
+0

Teşekkürler! Bunu şimdi kontrol edeceğim. – Pandincus

+0

@Chris Hynes: Cevabınız ve örnek kodunuz tam olarak ihtiyacım olan şeydi. Örnek kodunuzu biraz değiştirdim çünkü bir XmlElement öğesinin Value özelliğini ayarlayamıyorsunuz (görünüşte) ve kodumu anlık olarak yanıtıma göndereceğim. Obalix'in çözümü de doğruydu, ama sadece bir cevabı kabul edebilirim ve örnek kod gerçekten yukarıda ve ötesinde idi - hayatımı kolaylaştırdım. Chris teşekkürler! – Pandincus

+0

Uygun şekilde değiştirildi - Aslında kodu çalıştırmadım, sadece yazdım * kızarma *. –

2

documentation devletler:

The parameter should correspond to a W3C type. The following table shows the W3C types, either XPath or XSLT, and the corresponding.NET class.

Ve aşağıdaki türlerini listeler:

  • Dize
  • Boole
  • Numara
  • Hedef Ağaç Parçası
  • düğüm kümesi
  • Düğüm

Yani yanıt iyi en azından doğrudan ... olamaz değil. Fakat sizin durumunuzdaki en iyi bahis, IMHO, Düğüm veya Düğüm Seti'dir.

+0

Aramak zorunda değilsiniz. XsltArgumentList.AddParam benim için değil. (Günün çok geç mi?) Bir Node ya da NodeSet'i iade etmeyi ve çalışıp çalışmadığını kontrol edeceğim. Teşekkür ederim! – Pandincus

İlgili konular