从子元素列表中只取中间的一个

发布于 2024-09-26 06:13:48 字数 6039 浏览 7 评论 0原文

你好,

我有一个问题和一个截止日期(我只知道在这个困境中有一些知情的点头)

背景:我需要以分层的方式存储数据元素。简而言之,我的 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 部分:(最后我听到了尖叫声)....使用现有的结构,我如何才能只检索我的 Series 元素之一而不是它的子元素,以便我可以单独更新其参数。

B 部分:这是格式化我的 XML 以实现这种非常有用的父子关系的正确方法吗?

干杯 Snark ...

PS 如果您愿意回答,我可以麻烦您简单描述一下所建议的解决方案吗?有效......我第一次使用 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;

                    }
                }
            }

Greetings,

I have a problem and a deadline (I just know there are some knowing nods at that plight)

Background: I had a need to store data elements in an hierarchical nature. In a nutshell my xml is a set of rules that instruct a graphical drawing engine to draw a number of series on a chart according to a strict parent child relationship. i.e. A series 'could' use for its source data the resultant series of its parent and so on and so on ... or it might not.
The power of this approach I thought was that if I ever needed to delete a parent series it was trivially simple to delete the parent xml node and ALL the dependant/child series/nodes would also be removed ... magic works like a charm .. I'm almost a LINQ convert.

I had an image to illustrate the
output but apparently I'm too much of
a newbie to allow images to be posted
.. so imagine 4 wavey lines drawn on
a chart 3 of them based upon the
previous and one just living large all
on its lonesome .. dumb image posting
rule but meh what ya gonna do :-( ..

The XML that represents this relationship is the following.

<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>

The problem I have found is that sometimes I need to change values in the parameter section of the XML I can target and retrieve the required node .. but that node also contains any of the child nodes as well.
For example if I retrieve XElement with an Name of "Series" and attribute ID of "2" I also get the Series entry for ID = 3 as well.

THE QUESTION Part A:(finally I hear the scream) .... with this existing structure how can I retrieve just one of my Series elements and not its children so I can update its parameters alone.

And Part B: Is this the correct way of formatting my XML to achieve this very useful parent child relationship ...

Cheers Snark ...

P.S. If your kind enough to answer, could I bother you for a minimal description of how the proposed solution works .... My first play with LINQ to XML and not as straight forward as I'd hoped I still think in terms of relational databases.

After reading the kind posts I tinkered a little an voila my extreme brute force approach (dont we all miss those days when elegant design was something only marketing execs spoke of to get the sale) .. any way .

           /// <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;

                    }
                }
            }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

碍人泪离人颜 2024-10-03 06:13:49

如果您使用 XPath,则很简单:

/Chart//Series[@ID='4']/Parameters/Param[@Name='Color']

将仅查找作为特定 Series 元素的直接子级的 Parameters 元素,并且仅查找指定的 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);

If you use XPath, it's straightforward:

/Chart//Series[@ID='4']/Parameters/Param[@Name='Color']

will find only the Parameters element that's an immediate child of the specific Series element, and only the specified Param element that's immediately under that Parameters element.

It will look everywhere in the document for that Series element, which is a little inefficient if you have a big document to search and you're doing this a lot; in that case it'd probably be worth building a map, e.g.:

var seriesMap = rootXElement
   .SelectXPathElements("//Series")
   .ToDictionary(x => x.Attribute("ID").Value);

Then you can get a given Param element like this:

string pattern = string.Format("Parameters/Param[@Name='{0}']", name);
seriesMap[id].SelectXPathElement(pattern);
残龙傲雪 2024-10-03 06:13:49

如果您将其视为 xml,那么您将始终拥有后代 - 否则您就会破坏 xml。但只要您只查看直接子级的 Parameters 就应该没问题。如果将其映射到对象模型,您将采用类似的方法,但您将忽略 Items (或任何您称为子成员的内容)。

没有“正确的方法”,但是,应该就足够了。在某些情况下,您可能想要考虑平面模型,但分层模型似乎适合此数据。通过“平面”模型,我的意思是您只需:

 <Series ID="1" ...>...</Series>
 <Series ID="2" ...>...</Series>
 <Series ID="3" ...>...</Series>
 <Series ID="4" ...>...</Series>

请注意,您仍然可以使用现有的 值来推断关联,而无需将其作为实际布局的一部分。我并不是说两者都正确 - 只是两者都是合法的。事实上,目前您有冗余,因为您通过结构通过值来表达这种关系;这很好,除非您犯了错误并更新了其中一个而不是另一个。

If you look at it as xml, you are always going to have the descendants - otherwise you are corrupting the xml. But as long as you only look at the Parameters of the immediate child that should be fine. If you map it to an object model you would have a similar approach, but you'd ignore the Items (or whatever you call the child member).

There is no "the correct way", but yes, that should suffice. In some cases you might want to consider a flat model, but hierarchical seems to suit this data OK. By a "flat" model I mean that you'd simply have:

 <Series ID="1" ...>...</Series>
 <Series ID="2" ...>...</Series>
 <Series ID="3" ...>...</Series>
 <Series ID="4" ...>...</Series>

Note you can still use the existing <Parent> value to infer the association without having it part of the actual layout. I'm not saying either is correct - merely that both are legal. Indeed, at the moment you have redundancy in that you express this relationship both through the structure and through the values; which is fine until you make a mistake and update one but not the other.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文