2016-09-07 111 views
2

我需要以某種方式處理/拼合傳入的xml。使用LINQ to 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> 

目標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元素節點讓所有不同的任務了。

另一個想法我是使用正則表達式在每個步驟,將緊隨其後的子節點開放<content>前關閉</content> innerxml結合起來,更新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'後代content'節點最頂層走,並通過創建一套新的扁平他們的節點,用'AddBeforeSelf'插入它們,然後刪除舊的(已經變平的)節點。 但是,你的想法似乎也工作得很好。 謝謝! –