如何在没有XSLT或SQL的情况下将具有子节点的一条XML记录转换为多条记录

时间:2013-07-09 20:22:10

标签: c# xml

我需要弄清楚如何使用C#将一个带有子节点的XML记录转换成多个记录。是的,我知道使用XSLT更容易做到这一点,但这不是一个选择。我有一个XML文件,必须修改为5种不同的用途,所以我需要一个共同的起点。

原谅我缺乏理解,但我找不到的东西似乎朝这个方向发展。一切都朝着另一个方向发展。这是我的代码和文件的示例。

源文件。

<inventoryitems>
  <inventoryitem>
    <id>11101</id>
    <displayname>LG HAMBURGER PATTY</displayname>
    <basemeasure>EACH</basemeasure>
    <reportingmeasure>EACH</reportingmeasure>
    <measures>
      <measure>
        <name>CS</name>
        <factor>1.000000</factor>
        <isactive>1</isactive>
      </measure>
      <measure>
        <name>ST</name>
        <factor>8.000000</factor>
        <isactive>1</isactive>
      </measure>
      <measure>
        <name>EACH</name>
        <factor>120.000000</factor>
        <isactive>1</isactive>
      </measure>
    </measures>
    <categories>
      <category>
        <name>MEATS</name>
      </category>
    </categories>
    <locations />
    <skus />
  </inventoryitem>
  <inventoryitem>
    <id>11102</id>
    <displayname>SM HAMBURGER PATTY</displayname>
    <basemeasure>EACH</basemeasure>
    <reportingmeasure>EACH</reportingmeasure>
    <measures>
      <measure>
        <name>ST</name>
        <factor>6.000000</factor>
        <isactive>1</isactive>
      </measure>
      <measure>
        <name>CS</name>
        <factor>1.000000</factor>
        <isactive>1</isactive>
      </measure>
      <measure>
        <name>EACH</name>
        <factor>96.000000</factor>
        <isactive>1</isactive>
      </measure>
    </measures>
    <categories>
      <category>
        <name>MEATS</name>
      </category>
    </categories>
    <locations />
    <skus />
  </inventoryitem>
  <inventoryitem>
    <id>11202</id>
    <displayname>BREAD  SM BUN 4</displayname>
    <basemeasure>EACH</basemeasure>
    <reportingmeasure>EACH</reportingmeasure>
    <measures>
      <measure>
        <name>TR</name>
        <factor>1.000000</factor>
        <isactive>1</isactive>
      </measure>
      <measure>
        <name>EACH</name>
        <factor>30.000000</factor>
        <isactive>1</isactive>
      </measure>
    </measures>
    <categories>
      <category>
        <name>BAKERY</name>
      </category>
    </categories>
    <locations />
    <skus />
  </inventoryitem>
</inventoryitems>

我需要得到的东西会是这样的。

<data>
  <row InventoryItemId="11201" ItemDescription="BREAD LG BUN 5" CategoryName="BAKERY" Measure="TR" />
  <row InventoryItemId="11201" ItemDescription="BREAD LG BUN 5" CategoryName="BAKERY" Measure="EACH" />
</data>

当只有一个节点时,我能够编写代码来将值模式化为属性,但是当存在具有多个值的子节点时,我无法做什么。

invlist = results.Substring(results.IndexOf("<inventoryitems>"), (results.IndexOf("</inventoryitemsresponsedata>") - results.IndexOf("<inventoryitems>")));

                XmlDocument doc = new XmlDocument();
                XmlNode nd = doc.CreateNode("element", "data", "");
                doc.AppendChild(nd);

                //XmlNode rw = doc.CreateNode("element", "row", "");
                //nd.AppendChild(rw);

                var invitems = new XmlDocument { InnerXml = invlist };

                XmlNode result = doc.ImportNode(invitems.DocumentElement, true);
                nd.AppendChild(result);

                XmlNodeList ndList = doc.SelectNodes("data/inventoryitems/inventoryitem");
                foreach (XmlNode id in ndList)
                {
                    XmlNode idnode = id.SelectSingleNode("id");
                    if (idnode != null)
                    {
                        XmlNode rw = doc.CreateNode("element", "row", "");
                        nd.AppendChild(rw);

                        var attribute = doc.CreateAttribute("InventoryItemId");
                        attribute.Value = idnode.InnerXml;

                        var Description = doc.CreateAttribute("ItemDescription");
                        Description.Value = id.SelectSingleNode("displayname").InnerXml;

                        rw.Attributes.Append(attribute);
                        rw.Attributes.Append(Description);

                    }

                    XmlNodeList msList = id.SelectNodes("measures/measure");
                    foreach (XmlNode mes in msList)
                    {
                        XmlNode msnode = mes.SelectSingleNode("name");
                        if (msnode != null)
                        {
                            var attribute = doc.CreateAttribute("Measure");
                            attribute.Value = msnode.InnerXml;
                            //rw.Attributes.Append(attribute);
                            mes.Attributes.Append(attribute);
                        } 
                    }
              }

任何帮助将不胜感激。

更新:这就是我得到的。

<data>
  <row InventoryItemId="11201" ItemDescription="BREAD LG BUN 5" CategoryName="BAKERY" />
  <inventoryitem>
    <measures>
      <measure Measure="TR"></measure>
      <measure Measure="EACH"></measure>
    </measures>
    <locations />
    <skus />
  </inventoryitem>
</data>

1 个答案:

答案 0 :(得分:0)

我明白了。通过将每个节点包装在行节点循环中,我得到了我正在寻找的结果。

                   var item = idnode.InnerXml;

                    XmlNodeList rwList = doc.SelectNodes(String.Format("data/row[@InventoryItemId='{0}']",item));
                    var rwCount = rwList.Count;
                    foreach (XmlNode rw in rwList)
                    {
                        XmlNodeList msList = id.SelectNodes("measures/measure");                        
                        foreach (XmlNode mes in msList)
                        {                            
                            XmlNode msnode = mes.SelectSingleNode("name");
                            {                                
                                var attribute = doc.CreateAttribute("Measure");
                                attribute.Value = msnode.InnerXml;

                                if (rwCount > 0)
                                {
                                    rw.Attributes.Append(attribute);
                                    rwCount--;
                                }
                                else
                                {
                                    XmlNode clonenode = rw.Clone();
                                    clonenode.Attributes.Append(attribute);
                                    nd.AppendChild(clonenode);
                                }
                            }
                        }
                    }