首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >构建XML文档的恰当而优雅的方法

构建XML文档的恰当而优雅的方法
EN

Code Review用户
提问于 2013-11-27 18:58:55
回答 3查看 3.6K关注 0票数 5

我需要构建以下XML文档

代码语言:javascript
复制
<?xml version="1.0"?>
<SFDocument>
    <TableID>5415</TableID>
    <PageSize>1</PageSize>
    <PageIndex>1</PageIndex>
    <MultiCompany>No</MultiCompany>
    <Language>1033</Language>
    <Fields>
        <Field>Operation No.</Field>
        <Field>Line No.</Field>
        <Field>Date</Field>
        <Field>Comment</Field>
    </Fields>
    <TableFilters>
        <TableFilter>
            <Field>Status</Field>
            <Filter>3</Filter>
        </TableFilter>
        <TableFilter>
            <Field>Prod. Order No.</Field>
            <Filter>101006</Filter>
        </TableFilter>
    </TableFilters>
    <Key>
        <Field>Routing Reference No</Field>
        <Field>10000</Field>
    </Key>
</SFDocument>

使用下面的代码,它可以工作,但它是否是正确的方法。

代码语言:javascript
复制
internal class Field
{
    public string Name { get; set; }
    public  const string FieldName = "Field";
}
internal class Key
{
    public string Field { get; set; }
    public  const string FieldName = "Field";
}

internal class TableFilter
{
    public string Field { get; set; }
    public string Filter { get; set; }
    public const string FieldName = "Field";
    public const string FilterName = "FilterName";
} 

void Main()
{
    //this part is just for the example, obviously, this would be passed as parameter
    var tableId = 5415;
    var pageSize = 1;
    var pageIndex = 1;
    var multiCompany = "No";
    var language = 1033;

    var fields = new List<Field>();
    fields.Add(new Field() {Name = "Operation No."});
    fields.Add(new Field() {Name = "Line No."});
    fields.Add(new Field() {Name = "Date"});
    fields.Add(new Field() {Name = "Comment"});

    var tableFilters = new List<TableFilter>();
    tableFilters.Add(new TableFilter() {Field = "Status", Filter = "3"});
    tableFilters.Add(new TableFilter() {Field = "Prod. Order No.", Filter = "101006"});

    var keys = new List<Key>();
    keys.Add(new Key() {Field = "Routing Reference No"});
    keys.Add(new Key() {Field = "10000"});

    //End of setup

    XDocument doc = new XDocument(new XElement("SFDocument",
                                      new XElement("TableId", tableId), 
                                      new XElement("PageSize", pageSize),
                                      new XElement("PageIndex", pageIndex),
                                      new XElement("MultiCompany", multiCompany),
                                      new XElement("Language", language),
                                      new XElement("Fields"),
                                        new XElement("TableFilters"),
                                        new XElement("Key")
                                        )
    );

    var xFields = doc.Element("SFDocument").Element("Fields");

    foreach (Field field in fields)
    {
        xFields.Add(new XElement(Field.FieldName, field.Name));
    }

    var xTableFilters = doc.Element("SFDocument").Element("TableFilters");

    foreach (TableFilter tableFilter in tableFilters)
    {
        var tf = new XElement("TableFilter");
        tf.Add(new XElement(TableFilter.FieldName, tableFilter.Field));
        tf.Add(new XElement(TableFilter.FilterName, tableFilter.Filter  ));
        xTableFilters.Add(tf);
    }

    var xKey = doc.Element("SFDocument").Element("Key");

    foreach (Key key in keys)
    {
        xKey.Add(new XElement(Key.FieldName, key.Field));
    }       
    doc.Dump();  //Using LinqPad
}
EN

回答 3

Code Review用户

回答已采纳

发布于 2013-11-28 20:14:41

最后,我更改了我的方法,并使用了一个序列化方法:

代码语言:javascript
复制
public static class SerializationHelper
{
    internal static string SerializeObject<T>(this T toSerialize)
    {
        var xmlSerializer = new XmlSerializer(toSerialize.GetType());
        var textWriter = new StringWriter();
        xmlSerializer.Serialize(textWriter, toSerialize);
        return textWriter.ToString();
    }
}
[Serializable]
public class SFDocument
{
    public int TableId { get; set; }
    public int PageSize { get; set; }
    public int PageIndex { get; set; }
    public string MultiCompany { get; set; }
    public int Language { get; set; }

        [XmlArrayItem("Field")]
        public List<string> Fields { get; set; }

        public List<TableFilter> TableFilters { get; set; }

        [XmlArrayItem("Field")]
        public List<string> Key { get; set; }
        public SFDocument(): this(5415, 1, 1, "No", 1033){}

        public SFDocument(int tableId, int pageSize, int pageIndex, string multiCompany, int language)
        {
            TableId = tableId;
            PageSize = pageSize;
            PageIndex = pageIndex;
            MultiCompany = multiCompany;
            Language = language;

            Fields = new List<string>();
            Key = new List<string>();
            TableFilters  = new List<TableFilter>();
        }
}   

[Serializable]
public class TableFilter
{
    public string Field { get; set; }
    public string Filter { get; set; }

    public TableFilter() {}

    public TableFilter(string field, string filter)
    {
        Field = field;
        Filter = filter;
    }
}

void Main()
{
    var sfd = new SFDocument();
    sfd.Fields.Add("Field1");
    sfd.Fields.Add("Field2");
    sfd.Fields.Add("Field3");
    sfd.Fields.Add("Field4");

    sfd.Key.Add("Key1");
    sfd.Key.Add("Key2");
    sfd.Key.Add("Key3");

    sfd.TableFilters.Add(new TableFilter("field1", "filter1"));
    sfd.TableFilters.Add(new TableFilter("field2", "filter2"));
    sfd.TableFilters.Add(new TableFilter("field3", "filter3"));
    sfd.SerializeObject().Dump();
}
票数 4
EN

Code Review用户

发布于 2013-11-29 01:05:27

使用XML序列化肯定是一种有效的方法。但是,如果您想继续使用LINQ,我将修改代码,使其更具声明性。这样,代码的结构将与XML的结构非常相似,因此更清楚地看到发生了什么:

代码语言:javascript
复制
XDocument doc = new XDocument(
    new XElement(
        "SFDocument",
        new XElement("TableId", tableId),
        new XElement("PageSize", pageSize),
        new XElement("PageIndex", pageIndex),
        new XElement("MultiCompany", multiCompany),
        new XElement("Language", language),
        new XElement(
            "Fields", fields.Select(field => new XElement(Field.FieldName, field.Name))),
        new XElement(
            "TableFilters",
            tableFilters.Select(
                tableFilter =>
                new XElement(
                    "TableFilter",
                    new XElement(TableFilter.FieldName, tableFilter.Field),
                    new XElement(TableFilter.FilterName, tableFilter.Filter)))),
        new XElement("Key", keys.Select(key => new XElement(Key.FieldName, key.Field)))));

尽管TableFilters元素对于这种方法来说可能太复杂了。但您可以轻松地将其重构为另一种方法:

代码语言:javascript
复制
private static XElement CreateTableFilters(IEnumerable<TableFilter> tableFilters)
{
    return new XElement(
        "TableFilters",
        tableFilters.Select(
            tableFilter =>
            new XElement(
                "TableFilter",
                new XElement(TableFilter.FieldName, tableFilter.Field),
                new XElement(TableFilter.FilterName, tableFilter.Filter))));
}

…

XDocument doc = new XDocument(
    new XElement(
        "SFDocument",
        new XElement("TableId", tableId),
        new XElement("PageSize", pageSize),
        new XElement("PageIndex", pageIndex),
        new XElement("MultiCompany", multiCompany),
        new XElement("Language", language),
        new XElement(
            "Fields", fields.Select(field => new XElement(Field.FieldName, field.Name))),
        CreateTableFilters(tableFilters),
        new XElement("Key", keys.Select(key => new XElement(Key.FieldName, key.Field)))));
票数 3
EN

Code Review用户

发布于 2013-11-27 22:58:30

回到使用.NET 2.0时,我编写了从XmlElement继承的Tag类和从XmlDocument继承的XmlBuilder。由于遗留的原因,我们仍然使用它,但我确信它可以作为几个扩展方法被重写成代码的一半。

下面是一个小样本:

代码语言:javascript
复制
XmlBuilder xml = new XmlBuilder("AmazonEnvelope");
xml.AddNamespace("noNamespaceSchemaLocation", "amzn-envelope.xsd");
XmlBuilder.Tag message = xml.FirstTag.AddTag("Message");
message.AddTag("MessageID", messageID++);
message.AddTag("OperationType", "PartialUpdate");

XmlBuilder.Tag product = message.AddTag("Product");
product.AddTag("SKU", part.ID);

if (part.upcCode.Length == 12)
{
    XmlBuilder.Tag UPC = product.AddTag("StandardProductID");
    UPC.AddTag("Type", "UPC");
    UPC.AddTag("Value", part.upcCode);
}
else if (part.upcCode.Length == 13)
{
    XmlBuilder.Tag UPC = product.AddTag("StandardProductID");
    UPC.AddTag("Type", "EAN");
    UPC.AddTag("Value", part.upcCode);
}

product.AddTag("ProductTaxCode", "A_GEN_TAX");
return xml.OuterXml

XmlBuilder构造函数只接受字符串并使用该字符串创建第一个节点:

代码语言:javascript
复制
_outerNode = new Tag(qualifiedName, this);
AppendChild(_outerNode);

xml.FirstTag只是一个将_outerNode作为Tag (而不是XmlElement)的调用。

等等..。

这让您可以轻松地添加许多逻辑(“我要添加这组标记吗?”),它不需要大量的news,以后您可以返回并向标记添加更多内容。

票数 1
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/36238

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档