Как объединить значения узлов XML в один узел, разделенный косой чертой каждые 2 значения - PullRequest
0 голосов
/ 13 октября 2019

У меня есть следующий XML-файл:

    <root>
        <table>
            <items>Item 1</items>
        </table>
        <table>
            <items>Item 2</items>
        </table>
        <table>
            <items>Item 3</items>
        </table>
        <table>
            <items>Item 4</items>
        </table>
        <table>
            <items>Item 5</items>
        </table>
        <table>
            <items>Item 6</items>
        </table>
        <table>
            <items>Item 7</items>
        </table>
        <table>
            <items>Item 8</items>
        </table>
    </root>

Я хочу объединить все значения элементов в один узел, чтобы использовать это значение узла в некотором фрагменте кода. Каждые 2 значения должны быть разделены знаком "/".

. Мне удалось написать некоторый код, и мой результат сейчас таков:

<root>
    <table>
        <items>Item 1, Item 2, Item 3, Item 4, Item 5, Item 6, Item 7, Item 8</items>
    </table>
</root>

Однако конечный результат должен выглядеть следующим образом:

<root>
    <table>
        <items>Item 1, Item 2 / Item 3, Item 4 / Item 5, Item 6 / Item 7, Item 8</items>
    </table>
</root>

РЕДАКТИРОВАТЬ: Это код, который я использовал для получения того, что у меня есть сейчас:

var input = "XML";

    XDocument doc = XDocument.Parse(input);

    XElement root = doc.Root;
    XElement parentTable = root.Element("parentTable");
    parentTable.Add(new XElement("components"));
    XElement components = parentTable.Element("components");
    ArrayList componentArray = new ArrayList();

    foreach (var d in doc.Descendants("table"))

    {
        componentArray.Add(d.Value + ", ");
    }

    components.Add(componentArray);

    doc.Save("XML");

Ответы [ 3 ]

2 голосов
/ 13 октября 2019

Простой с xml linq

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.IO;

namespace ConsoleApplication1
{
    class Program
    {
        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        {
            string input = File.ReadAllText(FILENAME);
            XDocument doc = XDocument.Parse(input);

            string[] data = doc.Descendants("items").Select(x => (string)x).ToArray();

            string splitData = string.Join(" / ", data.Select((x, i) => new { data = x, index = i }).GroupBy(x => x.index / 2).Select(x => string.Join(" , ", x.Select(y => y.data))));

            XElement newDoc = new XElement("root", new XElement("table", new XElement("items", splitData)));
        }
    }
}
0 голосов
/ 13 октября 2019

Просто используйте логическую переменную в качестве флага того, какое значение вставлять на каждой итерации.

var doc = XDocument.Load("test.xml");

var sb = new StringBuilder();
bool flag = true;
var nodes = doc.Root.Elements("table").Elements("items").ToList();

for (int i = 0; i < nodes.Count; i++)
{
    sb.Append(nodes[i].Value);

    if (i == nodes.Count - 1)
        break;

    sb.Append(flag ? ", " : " / ");

    flag = !flag;
}

var newDoc = new XDocument(
    new XElement("root",
        new XElement("table",
            new XElement("items", sb.ToString()))));

newDoc.Save(Console.Out);

Вы можете сделать это без дополнительной переменной:

for (int i = 0; i < nodes.Count; i++)
{
    sb.Append(nodes[i].Value);

    if (i == nodes.Count - 1)
        break;

    sb.Append(i % 2 == 0 ? ", " : " / ");
}
0 голосов
/ 13 октября 2019

Одним из способов достижения вашей цели является использование таблицы стилей XSLT-1.0, предпочтительного метода для обработки данных XML.

Итак, вы можете выполнить эту таблицу стилей XSLT-1.0 (здесь она называется trans.xslt) из C #:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" version="1.0">
<xsl:output method="xml" encoding="UTF-8" omit-xml-declaration="yes" />
<xsl:strip-space elements="*" />

    <xsl:template match="/root">
        <xsl:copy>
            <table>
                <items><xsl:apply-templates select="table"/></items>
            </table>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="table[position() mod 2 != 0]">
        <xsl:value-of select="items" />
    </xsl:template>    

    <xsl:template match="table[position() mod 2 = 0]">
        <xsl:value-of select="concat(', ', items)" />
        <xsl:if test="position() != last()"><xsl:text> / </xsl:text></xsl:if>
    </xsl:template>

</xsl:stylesheet>

с этим кодом C #, описанным в этом SO ответе :

var myXslTrans = new XslCompiledTransform(); 
myXslTrans.Load("trans.xslt"); 
myXslTrans.Transform("input.xml", "output.xml"); 

Его вывод (output.xml):

<root>
    <table>
        <items>Item 1, Item 2 / Item 3, Item 4 / Item 5, Item 6 / Item 7, Item 8</items>
    </table>
</root>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...