2016-09-07 8 views
2

Мне нужно обработать/сгладить входящий XML-код определенным образом.Сгладить xml с текстовыми и узлами элементов, используя LINQ to XML

Источник XML:

<paragraph> 
     This <content styleCode="Underline">is</content> 
     <content styleCode="Italic"> 
      <content styleCode="Underline"> 
       <content styleCode="Bold">hello</content> world 
      </content> test</content> <content styleCode="Bold">example</content> here. 
    </paragraph> 

Target XML:

<paragraph> 
    This <content styleCode="underline">is</content> <content styleCode="italic underline bold">hello</content> <content styleCode="italic underline">world</content> <content styleCode="italic">test</content> <content styleCode="Bold">example</content> here. 
</paragraph> 

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

Еще одна идея у меня было использовать регулярные выражения, чтобы объединить InnerXml на каждом шагу, вставив закрытия </content> до того дочернего узла и открытия <content> сразу после него, обновить styleCode атрибуты соответственно, затем и удалить старый узел. Мне тоже не удалось это сделать.

Любые идеи, решения очень ценятся.

Кроме объединения и уплощение content узлов, у меня есть к нижнему регистру комбинированных styleCode атрибуты, это самая легкая часть, очевидно:

XDocument xml = XDocument.Parse(sourceXml); 
XName contentNode = XName.Get("content", "mynamespace"); 
var contentNodes = xml.Descendants(contentNode); 
var renames = contentNodes.Where(x => x.Attribute("styleCode") != null); 
foreach (XElement node in renames.ToArray()) 
{ 
    node.Attribute("styleCode").Value = node.Attribute("styleCode").Value.ToLower(); 
} 
+0

У вас есть контроль над XML? Вы можете попробовать обернуть текст в '' в теге 'CDATA', но если вам понадобится некоторая гимнастика, чтобы манипулировать дочерними элементами' '. – Tim

+0

Я не контулирую исходный XML, я мог бы обернуть его в CDATA для обработки, хотя, я ищу эту «гимнастику», хотя –

+0

Нет других тегов внутри? Только «контент», правильно? – SergeyS

ответ

2

Вы можете сделать это рекурсивно - перейти от узла к узлу сбора стилей, когда дело доходит до текста, оберните его тегом контента всеми найденными тегами. Код, указанный ниже:

static void MergeStyles(string xml) 
{ 
    XDocument doc = XDocument.Parse(xml); 
    var desc = doc.Document.Elements(); 
    Go(doc.Root, new List<string>()); 
    Console.WriteLine(target); 
} 

static string target = ""; 
static void Go(XElement node, List<string> styles) 
{ 
    foreach (var child in node.Nodes()) 
    { 
     if (child.NodeType == XmlNodeType.Text) 
     { 
      if (styles.Count > 0) 
      { 
       target += string.Format(
        "<content styleCode=\"{0}\">{1}</content>", 
        string.Join(" ", styles.Select(s => s.ToLower())), 
        child.ToString(SaveOptions.DisableFormatting)); 
      } 
      else 
      { 
       target += child.ToString(SaveOptions.DisableFormatting); 
      } 
     } 
     else if (child.NodeType == XmlNodeType.Element) 
     { 
      var element = (XElement)child; 
      if (element.Name == "content") 
      { 
       string style = element.Attributes("styleCode").Single().Value; 
       styles.Add(style); 
       Go(element, styles); 
       styles.RemoveAt(styles.Count - 1); 
      } 
     } 
    } 
} 
+0

Я закончил тем, что шел только через самый верхний уровень узлов «content», у которых есть «контентные» потомки и сплющены их, создав новый набор узлов, вставил их с помощью «AddBeforeSelf» и после всех удаленных старых (уже сплющенных) узлов. Но ваша идея, похоже, работает очень хорошо. Спасибо! –

 Смежные вопросы

  • Нет связанных вопросов^_^