Linq to XML для сравнения строк - PullRequest
2 голосов
/ 02 февраля 2012

Я пытаюсь написать кусок кода, который получает строку, использует данные в этой строке, чтобы внести изменения в другую строку, а затем сохраняет другую строку

Я бы предпочел сделать это с помощью linq, так как я в некоторой степени знаком с ним, хотя это не значит, что я абсолютно недалекий.

В любом случае, полученная строка имеет вид, подобный

"<?xml version=\"1.0\" encoding=\"utf-8\"?><Root><Value><Code>AAA</Code><Description>First description</Description><Bool>Y</Bool></Value><Value><Code>BBB</Code><Description>Second description</Description><Bool>Y</Bool></Value><Value><Code>CCC</Code><Description>Third description</Description><Bool>N</Bool></Value></Root>";

или с правильным форматированием

    "<?xml version=\"1.0\" encoding=\"utf-8\"?>
    <Root>
        <Value>
            <Code>AAA</Code>
            <Description>First description</Description>
            <Bool>Y</Bool>
        </Value>
        <Value>
            <Code>BBB</Code>
            <Description>Second description</Description>
            <Bool>Y</Bool>
        </Value>
        <Value>
            <Code>CCC</Code>
            <Description>Third description</Description>
            <Bool>N</Bool>
        </Value>
    </Root>"

и, например. другое значение как

    "<?xml version=\"1.0\" encoding=\"utf-8\"?>
    <Root>
        <Value>
            <Code>111</Code>
            <Description>111 description</Description>
            <Bool>Y</Bool>
        </Value>
        <Value>
            <Code>AAA</Code>
            <Description>First description</Description>
            <Bool>Y</Bool>
        </Value>
        <Value>
            <Code>222</Code>
            <Description>222 description</Description>
            <Bool>Y</Bool>
        </Value>
        <Value>
            <Code>BBB</Code>
            <Description>Second description</Description>
            <Bool>Y</Bool>
        </Value>
        <Value>
            <Code>333</Code>
            <Description>333 description</Description>
            <Bool>Y</Bool>
        </Value>
        <Value>
            <Code>CCC</Code>
            <Description>Third description</Description>
            <Bool>Y</Bool>
        </Value>
    </Root>"

такой же формы, но с большим количеством значений и со всеми Bools, установленными на Y. Все, что я хочу сделать, - это найти все коды с bool, установленным на N, и установить эти Bools в новом XML на N.

поэтому результатом объединения обоих этих элементов будет новый xml, но значение с кодом CCC будет иметь Bool, установленный как N., так:

    "<?xml version=\"1.0\" encoding=\"utf-8\"?>
    <Root>
        <Value>
            <Code>111</Code>
            <Description>111 description</Description>
            <Bool>Y</Bool>
        </Value>
        <Value>
            <Code>AAA</Code>
            <Description>First description</Description>
            <Bool>Y</Bool>
        </Value>
        <Value>
            <Code>222</Code>
            <Description>222 description</Description>
            <Bool>Y</Bool>
        </Value>
        <Value>
            <Code>BBB</Code>
            <Description>Second description</Description>
            <Bool>Y</Bool>
        </Value>
        <Value>
            <Code>333</Code>
            <Description>333 description</Description>
            <Bool>Y</Bool>
        </Value>
        <Value>
            <Code>CCC</Code>
            <Description>Third description</Description>
            <Bool>N</Bool>
        </Value>
    </Root>"

Мне кажется, что должен быть невероятно простой способ сделать это с использованием Linq to XML, но я уже некоторое время работаю над этим, и моя неопытность с XML, кажется, показывает, что у меня довольно немного проблем с этим.

Любая помощь будет принята с благодарностью.

Спасибо

Ответы [ 3 ]

2 голосов
/ 02 февраля 2012

Что-то подобное?

using System.Linq;
using System.Xml.Linq;

namespace ConsoleApplication1
{
    class Program
    {
        static XElement Join(XElement xmlOne, XElement xmlTwo)
        {
            return new XElement(
                "Root",
                    xmlOne.Elements("Value").Concat(xmlTwo.Elements("Value")).GroupBy(element => element.Element("Code").Value).Select(
                        group =>
                            new XElement("Value",
                                new XElement("Code", group.First().Element("Code").Value),
                                new XElement("Description", group.First().Element("Description").Value),
                                new XElement("Bool", group.Any(elem => elem.Element("Bool").Value == "N") ? "N" : "Y"))).ToArray());

        }

        static void Main(string[] args)
        {
            var xmlOne = XElement.Parse("<?xml version=\"1.0\" encoding=\"utf-8\"?>    <Root>        <Value>            <Code>AAA</Code>            <Description>First description</Description>            <Bool>Y</Bool>        </Value>        <Value>            <Code>BBB</Code>            <Description>Second description</Description>            <Bool>Y</Bool>        </Value>        <Value>            <Code>CCC</Code>            <Description>Third description</Description>            <Bool>N</Bool>        </Value>    </Root>");
            var xmlTwo = XElement.Parse("<?xml version=\"1.0\" encoding=\"utf-8\"?>    <Root>        <Value>            <Code>111</Code>            <Description>111 description</Description>            <Bool>Y</Bool>        </Value>        <Value>            <Code>AAA</Code>            <Description>First description</Description>            <Bool>Y</Bool>        </Value>        <Value>            <Code>222</Code>            <Description>222 description</Description>            <Bool>Y</Bool>        </Value>        <Value>            <Code>BBB</Code>            <Description>Second description</Description>            <Bool>Y</Bool>        </Value>        <Value>            <Code>333</Code>            <Description>333 description</Description>            <Bool>Y</Bool>        </Value>        <Value>            <Code>CCC</Code>            <Description>Third description</Description>            <Bool>Y</Bool>        </Value>    </Root>");
            var result = Join(xmlOne, xmlTwo);
        }
    }
}
0 голосов
/ 02 февраля 2012

Если ваш первый xml хранится в «doc1.xml», а второй - в «doc2.xml», вы можете достичь своей цели, просто выполнив следующее:

XElement doc1 = XElement.Load("doc1.xml");
XElement doc2 = XElement.Load("doc2.xml");

var pairs = from v1 in doc1.Elements("Value")
    join v2 in doc2.Elements("Value")
    on v1.Element("Code").Value equals v2.Element("Code").Value
    select new {v1, v2};

foreach (var pair in pairs)
    pair.v1.Element("Bool").Value = pair.v2.Element("Bool").Value;

Приведенный выше кодманипулирует doc1 на основе doc2.Затем вы можете сохранить результат в новом файле, например "doc3.xml":

doc1.Save("doc3.xml");
0 голосов
/ 02 февраля 2012

Вот еще одно решение, но оно больше похоже на использование linq, а не на linq:

string srcString = "<?xml version=\"1.0\" encoding=\"utf-8\"?><Root><Value><Code>AAA</Code><Description>First description</Description><Bool>Y</Bool></Value><Value><Code>BBB</Code><Description>Second description</Description><Bool>Y</Bool></Value><Value><Code>CCC</Code><Description>Third description</Description><Bool>N</Bool></Value></Root>";
string targetString = "<?xml version=\"1.0\" encoding=\"utf-8\"?><Root><Value><Code>111</Code><Description>111 description</Description><Bool>Y</Bool></Value><Value><Code>AAA</Code><Description>First description</Description><Bool>Y</Bool></Value><Value><Code>222</Code><Description>222 description</Description><Bool>Y</Bool></Value><Value><Code>BBB</Code><Description>Second description</Description><Bool>Y</Bool></Value><Value><Code>333</Code><Description>333 description</Description><Bool>Y</Bool></Value><Value><Code>CCC</Code><Description>Third description</Description><Bool>Y</Bool></Value></Root>";

XDocument srcDocument = XDocument.Parse( srcString );
XDocument targetDocument = XDocument.Parse( targetString );

// find all Value-elements with Bool = 'N' from the srcString
var srcData = from data in srcDocument.Element( "Root" ).Elements( "Value" )
              where string.Compare( data.Element( "Bool" ).Value.ToString( ), "N", true ) == 0
              select new { Code = data.Element( "Code" ).Value,
                           Description = data.Element( "Description" ).Value,
                           Bool = data.Element( "Bool" ).Value };

foreach( var item in srcData )
{
    var xmlData = from data in targetDocument.Element( "Root" ).Elements( "Value" )
                  where string.Compare( data.Element( "Code" ).Value.ToString( ), item.Code, true ) == 0
                  select data;

    foreach( var data in xmlData )
    {
        data.Element( "Bool" ).Value = "N";
    }
}

var finalString = targetDocument.ToString( );
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...