2012-11-12 54 views
3

我有一個很大的.net類和幾個xslt文件。我正在序列化我的對象以用我的xslt文件進行轉換。用XSLT轉換序列化的.net對象

我的班級的名字是Application,它有一個Applicant屬性,其中包含一組應用程序。

public class Application 
{ 
    public Person Applicant { get; set; } 
} 

public class Person 
{ 
    public List<Application> Applications { get; set; } 
} 

當我序列化我的類的實例,通常是我獲得的XML包含Z:參考值=「I18」屬性,以防止無限XML創建描述現有的參考性。但是這種情況改變了必須在我的Xslt文件中寫入的Xpath表達式。

我有機會序列化包含真實實體值的對象而不是z:參考指定深度的標記嗎?

這裏是我的序列化代碼:

public string Serialize(object input) 
{ 
    XmlDocument XmlDoc = new XmlDocument(); 
    DataContractSerializer xmlDataContractSerializer = 
     new DataContractSerializer(input.GetType()); 
    MemoryStream MemStream = new MemoryStream(); 
    try 
    { 
     xmlDataContractSerializer.WriteObject(MemStream, input); 
     MemStream.Position = 0; 
     XmlDoc.Load(MemStream); 
     return XmlDoc.InnerXml; 
    } 
    finally 
    { 
     MemStream.Close(); 
    } 
} 

由於提前,

阿尼爾

回答

2

沒有,基本上是這樣。你應該,但是,能夠使用這樣的:

<xsl:key name="ids" match="*[@z:Id]" use="@z:Id"/> 

,然後使用XSL key函數傳遞當前節點,其中zxmlns別名http://schemas.microsoft.com/2003/10/Serialization/@z:Ref - 將至少保持用法始終如一。


完整的示例 - XSLT第一( 「my.xslt」):

<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/" 
    xmlns:dcs="http://schemas.datacontract.org/2004/07/" 
> 
    <xsl:key name="ids" match="*[@z:Id]" use="@z:Id"/> 
    <xsl:output method="xml" indent="yes"/> 

    <xsl:template match="*[@z:Ref]"> 
    <xsl:param name="depth" select="5"/> 
    <xsl:apply-templates select="key('ids', @z:Ref)"> 
     <xsl:with-param name="depth" select="$depth"/> 
    </xsl:apply-templates> 
    </xsl:template> 
    <xsl:template match="*[@z:Id]"> 
    <xsl:param name="depth" select="5"/>  
    <xsl:value-of select="$depth"/>: <xsl:value-of select="name()"/><xsl:text xml:space="preserve"> 
</xsl:text> 
    <xsl:if test="$depth > 0"> 
     <xsl:apply-templates select="dcs:*"> 
     <xsl:with-param name="depth" select="($depth)-1"/> 
     </xsl:apply-templates> 
    </xsl:if> 
    </xsl:template> 
</xsl:stylesheet> 

注意,這經由$depth參數(遞減)行走5級;關鍵部分是任何元素*[@z:Ref]上的初始match,然後使用key將相同請求代理到原始元素,通過@z:Id解析。這意味着,當我們正在向子元素,我們只需要使用類似:

<xsl:apply-templates select="dcs:*"/> 

雖然我們可以明顯更爲精細,例如:

<xsl:apply-templates select="dcs:Foo"/> 

還要注意添加Foo特異性match,你可以這樣:

<xsl:template match="dcs:Foo[@z:Id]"><!-- --></xsl:template> 

,以確保我們的*[@z:Ref]比賽繼續處理參考forwardi NG。

和C#:

using System; 
using System.IO; 
using System.Runtime.Serialization; 
using System.Text; 
using System.Xml; 
using System.Xml.Xsl; 
[DataContract] 
public class Foo 
{ 
    [DataMember] 
    public Bar Bar { get; set; } 
} 
[DataContract] 
public class Bar 
{ 
    [DataMember] 
    public Foo Foo { get; set; } 
} 
static class Program 
{ 
    static void Main() 
    { 
     var foo = new Foo(); 
     var bar = new Bar(); 
     foo.Bar = bar; 
     bar.Foo = foo; 
     using (var ms = new MemoryStream()) 
     { 
      var ser = new DataContractSerializer(typeof(Foo), new DataContractSerializerSettings { 
       PreserveObjectReferences = true 
      }); 
      ser.WriteObject(ms, foo); 
      Console.WriteLine(Encoding.UTF8.GetString(ms.GetBuffer(), 0, (int)ms.Length)); 
      Console.WriteLine(); 
      ms.Position = 0; 
      var xslt = new XslCompiledTransform(); 
      xslt.Load("my.xslt"); 
      using (var reader = XmlReader.Create(ms)) 
      { 
       xslt.Transform(reader, null, Console.Out); 
      } 
     } 
     Console.WriteLine(); 
     Console.WriteLine("press any key"); 
     Console.ReadKey(); 
    } 
} 
+0

我無法理解你的觀點?你能否用另一種方式解釋它? – anilca

+0

@anilca「不,你不能讓它遞歸一點 - 但你至少可以很容易地在對象之間跳轉,通過使用xsl -key」 –

+0

如何到達使用引用的實體xsl鍵? – anilca