gpt4 book ai didi

c# - 使用 XSLT 转换序列化的 .net 对象

转载 作者:数据小太阳 更新时间:2023-10-29 02:36:25 24 4
gpt4 key购买 nike

我有一个很大的 .net 类和一些 xslt 文件。我正在序列化我的对象以使用我的 xslt 文件进行转换。

我的类(class)名称是 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();
}
}

提前致谢

阿尼尔

最佳答案

不,基本上。但是,您应该能够使用类似的东西:

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

然后使用xsl key函数传递当前节点的@z:Ref,其中z是一个xmlns http://schemas.microsoft.com/2003/10/Serialization/ 的别名 - 这至少会在整个过程中保持相同的用法。


完整示例 - 首先是 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"/>

另请注意,要添加特定于 Foomatch,您需要添加:

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

关于c# - 使用 XSLT 转换序列化的 .net 对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13339999/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com