2012-11-12 19 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