public struct Parameter
{
public Parameter(string name, string type, string parenttype)
{
this.Name = name;
this.Type = type;
this.ParentType = parenttype;
}
public string Name;
public string Type;
public string ParentType;
}
以下值存储在参数:
的数组中Name Type ParentType
-------------------------------------------------------
composite CompositeType
isThisTest boolean
BoolValue boolean CompositeType
StringValue string CompositeType
AnotherType AnotherCompositeType CompositeType
account string AnotherCompositeType
startdate date AnotherCompositeType
我想读这个来构建一个xml。类似的东西:
<composite>
<BoolValue>boolean</BoolValue>
<StringValue>string</StringValue>
<AnotherType>
<account>string</account>
<startdate>date</startdate>
</AnotherType>
<composite>
<isThisTest>boolean</isThisTest>
我使用以下逻辑来读取值:
foreach (Parameter parameter in parameters)
{
sb.Append(" <" + parameter.Name + ">");
//HERE: need to check parenttype and get all it's child elements
//
sb.Append("</" + parameter.Name + ">" + CrLf);
}
是否有更简单的方法来读取数组以获取父母和他们的孩子?可能正在使用LINQ?我还在.Net 3.5上。通过示例代码感谢任何建议:)
答案 0 :(得分:5)
你可以写一点递归方法来解决这个问题:
IEnumerable<XElement> GetChildren ( string rootType, List<Parameter> parameters )
{
return from p in parameters
where p.ParentType == rootType
let children = GetChildren ( p.Type, parameters )
select children.Count() == 0 ?
new XElement ( p.Name, p.Type ) :
new XElement ( p.Name, children );
}
每次调用都会构建一个XElements的Enumerable,其中包含父级具有传入类型的参数。 select再次递归到方法中,再次找到每个Element的子节点。
请注意,这确实假设数据已正确形成。如果两个参数相互作为父项,则会出现Stack Overflow。
魔法在XElements类(Linq to Xml)中,它接受XElements的可枚举来构建像Xml结构的树。
第一次调用,传递null(或使用默认参数,如果使用C#4)作为rootType。使用如下:
void Main()
{
var parameters = new List<Parameter> {
new Parameter {Name = "composite", Type = "CompositeType" },
new Parameter {Name = "isThisTest", Type = "boolean" },
new Parameter {Name = "BoolValue", Type = "boolean", ParentType = "CompositeType" },
new Parameter {Name = "StringValue", Type = "string", ParentType = "CompositeType" },
new Parameter {Name = "AnotherType", Type = "AnotherCompositeType", ParentType = "CompositeType" },
new Parameter {Name = "account", Type = "string", ParentType = "AnotherCompositeType" },
new Parameter {Name = "startdate", Type = "date", ParentType = "AnotherCompositeType" }
};
foreach ( var r in GetChildren ( null, parameters ) )
{
Console.WriteLine ( r );
}
}
输出:
<composite>
<BoolValue>boolean</BoolValue>
<StringValue>string</StringValue>
<AnotherType>
<account>string</account>
<startdate>date</startdate>
</AnotherType>
</composite>
<isThisTest>boolean</isThisTest>
修改强>
在回复您的评论时,XElement为您提供了两个输出字符串的选项。
ToString()将输出格式化的Xml。
ToString(SaveOptions)允许您指定格式化或未格式化的输出以及省略重复的命名空间。
我确定你可以调整解决方案以使用StringBuilder,如果你真的不得不这样做,虽然它可能不会那么优雅..
答案 1 :(得分:1)
看起来你想要使用递归方法,例如:
string GetChildren(Parameter param, string indent)
{
StringBuilder sb = new StringBuilder();
if (HasChildren(param))
{
sb.AppendFormat("{0}<{1}>{2}", indent, param.Name, Environment.NewLine);
foreach (Parameter child in parameters.Where(p => p.ParentType == param.Type))
{
sb.Append(GetChildren(child, indent + " "));
}
sb.AppendFormat("{0}</{1}>{2}", indent, param.Name, Environment.NewLine);
}
else
{
sb.AppendFormat("{0}<{1}>{2}</{1}>{3}", indent, param.Name, param.Type, Environment.NewLine);
}
return sb.ToString();
}
查看参数是否具有子节点的方法如下所示:
bool HasChildren(Parameter param)
{
return parameters.Any(p => p.ParentType == param.Type);
}
集合parameters
可以定义为IEnumerable<Parameter>
,可以使用List<Parameter>
来实现。