问候,
我有一个问题和一个截止日期(我只知道在这个困境中有一些知道的点头)
背景:我需要以分层的方式存储数据元素。简而言之,我的xml是一组规则,用于指示图形绘制引擎根据严格的父子关系在图表上绘制多个系列。即一系列'可以'用于其源数据,其父系列的结果系列等等......或者它可能不会。 我认为这种方法的强大之处在于,如果我需要删除父系列,删除父xml节点非常简单,所有依赖/子系列/节点也将被删除......魔法就像魅力一样。我几乎是LINQ转换器。
我有一张图片来说明 输出,但显然我太多了 允许发布图像的新手 ..所以想象一下画出4条波浪线 基于的图表3 以前和一个只是生活大 在它寂寞...愚蠢的图像张贴 但是,我要做什么:-( ..
表示此关系的XML如下所示。
<Chart>
<Chart_Config AxisClear="False">
<Color>white</Color>
<Panels Drawn="True">3</Panels>
<SeriesCount>5</SeriesCount>
<ChartStyle>Candle</ChartStyle>
<DataMode>Daily</DataMode>
</Chart_Config>
<Series ID="0" Drawn="True">
<Name>0.AAC</Name>
<StockCode>AAC</StockCode>
<TID>0</TID>
<IndID>-1</IndID>
<PID>0</PID>
<iType>0</iType>
<Parent>0</Parent>
<Series ID="1" Drawn="True">
<Name>1.SMA</Name>
<StockCode>AAC</StockCode>
<TID>0.AAC</TID>
<IndID>0</IndID>
<PID>2</PID>
<iType>1</iType>
<Parent>0.AAC</Parent>
<Parameters>
<Param Name="Period" Type="Integer" Min="1" Max="999">10</Param>
<Param Name="Color" Type="Color" Min="0" Max="0">0, 0, 192</Param>
<Param Name="Transparency" Type="Integer" Min="0" Max="100">0</Param>
<Param Name="Width" Type="Integer" Min="1" Max="99">2</Param>
</Parameters>
<Series ID="2" Drawn="True">
<Name>2.SMA</Name>
<StockCode>AAC</StockCode>
<TID>1.SMA</TID>
<IndID>0</IndID>
<PID>0</PID>
<iType>1</iType>
<Parent>1.SMA</Parent>
<Parameters>
<Param Name="Period" Type="Integer" Min="1" Max="999">20</Param>
<Param Name="Color" Type="Color" Min="0" Max="0">0, 192, 0</Param>
<Param Name="Transparency" Type="Integer" Min="0" Max="100">0</Param>
<Param Name="Width" Type="Integer" Min="1" Max="99">2</Param>
</Parameters>
<Series ID="3" Drawn="True">
<Name>3.SMA</Name>
<StockCode>AAC</StockCode>
<TID>2.SMA</TID>
<IndID>0</IndID>
<PID>0</PID>
<iType>1</iType>
<Parent>2.SMA</Parent>
<Parameters>
<Param Name="Period" Type="Integer" Min="1" Max="999">30</Param>
<Param Name="Color" Type="Color" Min="0" Max="0">192, 0, 192</Param>
<Param Name="Transparency" Type="Integer" Min="0" Max="100">0</Param>
<Param Name="Width" Type="Integer" Min="1" Max="99">2</Param>
</Parameters>
</Series>
</Series>
</Series>
<Series ID="4" Drawn="True">
<Name>4.SMA</Name>
<StockCode>AAC</StockCode>
<TID>0.AAC</TID>
<IndID>0</IndID>
<PID>3</PID>
<iType>1</iType>
<Parent>0.AAC</Parent>
<Parameters>
<Param Name="Period" Type="Integer" Min="1" Max="999">40</Param>
<Param Name="Color" Type="Color" Min="0" Max="0">192, 0, 0</Param>
<Param Name="Transparency" Type="Integer" Min="0" Max="100">0</Param>
<Param Name="Width" Type="Integer" Min="1" Max="99">2</Param>
</Parameters>
</Series>
</Series>
</Chart>
我发现的问题是,有时我需要更改我可以定位的XML的参数部分中的值并检索所需的节点..但该节点也包含任何子节点。 例如,如果我检索名称为“Series”且属性ID为“2”的XElement,我也会获得ID = 3的Series条目。
问题A部分:(最后我听到了尖叫声)....使用这个现有的结构,我如何只检索我的一个系列元素而不是它的子元素,这样我就可以单独更新它的参数。
和B部分:这是格式化我的XML以实现这个非常有用的父子关系的正确方法......
干杯斯纳克......
P.S。如果您有足够的回答,我是否可以打扰您对提议的解决方案如何工作的最小描述....我第一次使用LINQ to XML而不是像我希望的那样直截了当我仍然认为关系数据库。
在阅读了那些帖子后,我讽刺了我的极端蛮力方法(我们都不会错过那些优雅的设计只是营销高管谈到要出售的东西)......任何方式。
/// <summary>
/// Updates Parameters in conjunction with the Modify paramteters Dialog
/// </summary>
/// <param name="Message"></param>
private void UpdateIndicatorParameters(IndicatorParamterUpdate Message)
{
IEnumerable<XElement> result;
/// Find the series
if (Message.isIndicator)
{
result = from e in ChartObj.ChartSeriesXMLRules.Descendants()
where (e.Name.ToString() == "Series" && e.Attribute("ID").Value == Message.IndicatorID)
select e;
}
else
{
// not relevant
}
var NodeOfInterest = result;
/// Find Parameter section
foreach (var el in result)
{
NodeOfInterest = el.Elements("Parameters");
}
/// Find individual paramters
var result2 = from e in NodeOfInterest.Descendants()
where e.Name.ToString() == "Param"
select e;
/// Update required paramter
foreach (var el in result2)
{
if (el.Attribute("Name").Value == Message.ParameterName)
{
el.Value = Message.Value;
}
}
}
答案 0 :(得分:1)
如果你使用XPath,它很简单:
/Chart//Series[@ID='4']/Parameters/Param[@Name='Color']
只会找到特定Parameters
元素的直接子元素的Series
元素,并且只会找到紧跟在该Param
元素下的指定Parameters
元素。
它会在文档中的任何位置查找Series
元素,如果你有一个大文档要搜索并且你正在做很多事情,那么效率会有点低效;在这种情况下,建立地图可能是值得的,例如:
var seriesMap = rootXElement
.SelectXPathElements("//Series")
.ToDictionary(x => x.Attribute("ID").Value);
然后你可以得到一个给定的Param
元素:
string pattern = string.Format("Parameters/Param[@Name='{0}']", name);
seriesMap[id].SelectXPathElement(pattern);
答案 1 :(得分:0)
如果你把它看作xml,你 总是会有后代 - 否则你就是在破坏xml。但只要你只看一下应该没事的直系孩子的Parameters
。如果将它映射到对象模型,您将采用类似的方法,但是您将忽略Items
(或者您称之为子成员的任何内容)。
没有“正确的方法”,但是,应该就足够了。在某些情况下,可能想要考虑 flat 模型,但层次结构似乎适合这些数据。通过“平面”模型,我的意思是你只需要:
<Series ID="1" ...>...</Series>
<Series ID="2" ...>...</Series>
<Series ID="3" ...>...</Series>
<Series ID="4" ...>...</Series>
请注意,您仍然可以使用现有的<Parent>
值来推断关联,而不将其作为实际布局的一部分。我不是说要么是正确的 - 只是两者都是合法的。实际上,目前你有冗余,你通过结构和通过值来表达这种关系;这是罚款,直到你犯了一个错误并更新一个而不是另一个。