Из списка дочерних элементов взять только один из середины - PullRequest
1 голос
/ 05 октября 2010

Привет,

У меня есть проблема и крайний срок (я просто знаю, что есть некоторые знающие кивки в этом тяжелом положении)

Справочная информация: мне нужно было хранить элементы данных в иерархическойприрода.В двух словах, мой 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-файла, на который я могу ориентироваться и получить требуемый узел ..., но этот узел также содержит любыедочерних узлов. Например, если я получаю XElement с именем «Series» и идентификатором атрибута «2», я также получаю запись Series дляID = 3.

ВОПРОС Часть A: (наконец, я слышу крик) .... с этой существующей структурой, как я могу получить только один из моих элементов Серии, а не его потомков, чтобы я мог обновитьтолько его параметры.

И Часть B: Это правильный способ форматирования моего XML для достижения этого очень полезного отношения родитель-потомок ...

Cheers Snark ...

PS Если вы достаточно любезны, чтобы ответить, могу я вас побеспокоить, чтобы дать минимальное описание того, как работает предлагаемое решение ... Моя первая игра с LINQ to XML и не такая прямолинейная, как я надеялся, я все еще думаю с точки зренияреляционные базы данных.

Прочитав добрые посты, я немного повозился с моим грубым подвигом (разве мы все не скучаем по тем дням, когда элегантный дизайн был тем, о чем говорили только маркетологи, чтобы добиться продажи) ... любым способом.1024 *

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

                    }
                }
            }

Ответы [ 2 ]

1 голос
/ 05 октября 2010

Если вы используете 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);
0 голосов
/ 05 октября 2010

Если вы посмотрите на него как на xml, вы всегда будете иметь потомков - иначе вы испортите xml. Но до тех пор, пока вы смотрите только на Parameters ближайшего ребенка, это должно быть хорошо. Если вы сопоставите его с объектной моделью, у вас будет аналогичный подход, но вы проигнорируете Items (или как вы называете дочерний элемент).

Не существует «правильного пути», но да, что должно быть достаточным. В некоторых случаях вы могли бы захотеть рассмотреть модель flat , но иерархические данные, похоже, подходят для этих данных. Под «плоской» моделью я имею в виду, что у вас будет просто:

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

Обратите внимание, что вы все еще можете использовать существующее значение <Parent>, чтобы вывести ассоциацию, не включив ее в фактический макет. Я не говорю, что или верны - просто оба законны. Действительно, в данный момент у вас есть избыточность в том смысле, что вы выражаете эти отношения как через структуру , так и через значения; это отлично , пока вы не сделаете ошибку и не обновите одно, но не другое.

...