【问题标题】:Generating C# code from XML: how to output '<' and '>'?从 XML 生成 C# 代码:如何输出 '<' 和 '>'?
【发布时间】:2013-11-05 01:28:32
【问题描述】:

我有一个从 XML 创建 C# 类的 XSLT。我正在使用

<xsl:output method="text"/>

创建一个文本文件。基本上我是从http://docstore.mik.ua/orelly/xml/jxslt/ch08_05.htm 获取代码并修改它以输出C#代码。

但是现在我需要输出类似的东西

class PersonValidator : AbstractValidator<Person>
{
    public PersonValidator()
    {
        RuleFor(obj => obj.LastName).NotEmpty();
        ...
    }
}

...但是无论我想输出 '' 我得到 '<'和'>'。

有没有一种简单的方法可以做到这一点?

编辑:

这是我当前的 XSLT(CDATA 不起作用!):

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" 
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text"/>
    <xsl:variable name="className" select="/Class/@Name"/>
    <xsl:variable name="entityId" select="(//Property)[1]/@Name"/>     
    <xsl:template match="/Class">using System;
using System.Linq;
using Core.Common.Core;
using FluentValidation;
using System.Collections.Generic;

namespace PersonDosimetry.Client.Entities.Constants
{
    public class <xsl:value-of select="$className"/>
       <xsl:text> : ObjectBase</xsl:text>
    {   
    <xsl:apply-templates select="Property" mode="generateField"/>
        <xsl:text>      
        #region Business-mapped Properties  
        </xsl:text>
        <xsl:apply-templates select="Property" mode="generateProperty"/>
        #endregion

        #region Validation

        class <xsl:value-of select="$className"/>Validator : AbstractValidator<![CDATA[<]]><xsl:value-of select="$className"/><![CDATA[>]]>
        {
            public <xsl:value-of select="$className"/>Validator()
            {               
                //RuleFor(obj =<![CDATA[>]]> obj.LastName).NotEmpty();
            }
        }

        protected override IValidator GetValidator()
        {
            return new <xsl:value-of select="$className"/>Validator();
        }

        #endregion
    }
}
</xsl:template>

    <!--
    *****************************************************************
    ** Generate a private field declaration.
    **************************************************************-->
    <xsl:template match="Property" mode="generateField"><xsl:text>  </xsl:text>
    <xsl:value-of select="@Type"/>
    <xsl:text> _</xsl:text>
    <xsl:value-of select="@Name"/>;
    </xsl:template>

    <!--
    *****************************************************************
    ** Generate a "get" method for a property.
    **************************************************************-->
    <xsl:template match="Property" mode="generateProperty">
        public <xsl:value-of select="@Type"/><xsl:text> </xsl:text><xsl:value-of select="@Name"/>
        {
            get { return _<xsl:value-of select="@Name"/>; }
            set
            {
                if (_<xsl:value-of select="@Name"/> != value)
                {
                    _<xsl:value-of select="@Name"/> = value;
                    OnPropertyChanged();
                }
            }
        }
    </xsl:template>
</xsl:stylesheet>

我的示例 XML:

<?xml version="1.0"?>
<Class Name="Person">
    <Property Name="PersonId" Type="Int32" />
    <Property Name="FirstNames" Type="String" />
    <Property Name="LastName" Type="String" />
    <Property Name="GenderTypeId" Type="Int32" />
    <Property Name="BirthDate" Type="DateTime" />
    <Property Name="InsuranceNumber" Type="String" />
    <Property Name="Country" Type="String" />
    <Property Name="Beruf" Type="String" />
</Class>

【问题讨论】:

  • CDATA 可能效果最好
  • 您能否向我们展示您当前尝试输出“”的 XSLT 代码?谢谢!
  • 是的,请向我们展示您的 XSLT 并告诉我们您使用的 XSLT 处理器。如果您使用的是xsl:output method="text",那么应该很容易输出&lt;&gt;,除非您使用的是不符合标准的XSLT 处理器。

标签: c# xml xslt code-generation


【解决方案1】:

问题在于我使用的 XSLT 处理器(此处的版本:http://www.codeproject.com/Articles/8823/A-better-MSXSL-EXE-Adding-the-ability-to-Transform)。我开始使用它是因为我的代码生成器需要处理几个文件,而我的印象是它与 MSXSL 没有什么不同。

我下载了MSXSL,使用 CDATA 一切顺利。

(后续问题是:如何在 .NET 中以编程方式进行正确的转换?或者是否有更好的 XSL 转换库可以使用?)

更新

JLRishe 的评论将我引向了正确的方向。我将上面提到的codeproject代码更改为以下,现在代码生成工作了:

class Program
{
    static void Main(string[] args)
    {
        if (args.Length != 3)
        {
            Console.WriteLine("You have not entered the correct parameters");
            return;
        }
        string xmlfile = args[0];
        string xslfile = args[1];
        string outfile = args[2];
        try
        {
            XPathDocument doc = new XPathDocument(xmlfile);
            XslCompiledTransform transform = new XslCompiledTransform();
            transform.Load(xslfile);
            XmlWriter writer = XmlWriter.Create(outfile, transform.OutputSettings);
            transform.Transform(doc, writer);
            writer.Close();
        }
        catch (Exception e)
        {
            Console.WriteLine(e.StackTrace);
        }
    }
}    

【讨论】:

  • 在 .NET 中,您应该使用 XslCompiledTransform class。如果您出于某种原因需要它们,它支持嵌入式脚本。另外,您不需要使用 CDATA 来完成此任务。如果在 XSLT 中使用&amp;lt;&amp;gt;,只要输出方法为text,它们应该输出为&lt;&gt;
【解决方案2】:

您应该查看Xml Serialization。您可以将对象转换为 xml 并转换回 c# 对象。这使我可以轻松地将任何对象存储为 xml 并快速将其反序列化回对象。

例如,我的对象被称为“MyObject”:

public object DeserializeXmlMyObj(String xml)
    {
        try
        {
            XmlSerializer serializer = new XmlSerializer(typeof(MyObject));

            MyObject obj = null;
            using (StringReader reader = new StringReader(xml))
            {
                obj = (MyObject)serializer.Deserialize(reader);
            }
            return obj ;
        }
        catch (Exception ex)
        {

            return null;
        }

    }

【讨论】:

  • 问题是关于将 XML 转换为 C#code,而不是关于反序列化对象。
  • @svick - 理解,但是,当您在上面的示例中反序列化 xml 时,它正在创建 c# 对象。虽然,这可能不是一个直接的答案,但它可能是他/她甚至没有考虑过的解决方案。我的意图是鼓励另一种方法。
  • 这没有任何意义。如果您尝试生成可以从代码中使用的 C# 类,那么一些反序列化的对象根本就不行。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-14
  • 2011-08-02
  • 2011-03-13
相关资源
最近更新 更多