3

大きな .net クラスといくつかの xslt ファイルがあります。xslt ファイルで変換するオブジェクトをシリアル化しています。

私のクラスの名前は Application で、アプリケーションのコレクションを含む Applicant プロパティがあります。

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

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

クラスのインスタンスをシリアル化するとき、通常、取得した Xml にはz:Ref="i18"属性が含まれており、既存の参照プロパティを記述する無限の Xml 作成を防ぎます。しかし、この状況により、Xslt ファイルに記述しなければならない必要な Xpath 式が変わります。

指定された深さのz:Refタグの代わりに、実際のエンティティ値を含むオブジェクトをシリアル化する機会はありますか?

ここに私のシリアル化コードがあります:

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();
    }
}

前もって感謝します、

アヌル

4

2 に答える 2

2

いいえ、基本的に。ただし、次のようなものを使用できるはずです。

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

次に、xsl関数を使用して、現在のノードのkeyを渡します。ここで、はエイリアスです。これにより、少なくとも全体を通して同じ使用法が維持されます。@z:Refzxmlnshttp://schemas.microsoft.com/2003/10/Serialization/


完全な例-xsltfirst( "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レベル歩くことに注意してください。match重要な部分は、任意の要素のイニシャルです。これは、を介して解決されるように、同じリクエストを元の要素にプロキシするために*[@z:Ref]使用されます。これは、子要素に移動するときに、次のようなものを使用する必要があることを意味します。key@z:Id

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

明らかにもっときめ細かくすることもできますが、たとえば次のようになります。

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

Foo-specificを追加するには、次を追加することにも注意してくださいmatch

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

*[@z:Ref]マッチが引き続き参照転送を処理するようにします。

そして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();
    }
}
于 2012-11-12T08:02:45.207 に答える
0

使ってみてXmlSerializer

TestClass TestObj = new TestClass();
XmlSerializer SerializerObj = new XmlSerializer(typeof(TestClass));
TextWriter WriteFileStream = new StreamWriter(@"C:\test.xml");
SerializerObj.Serialize(WriteFileStream, TestObj);
WriteFileStream.Close();

http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlserializer.aspx

于 2012-11-12T08:16:05.567 に答える