2016-09-07 5 views
2

着信xmlを特定の方法で処理/平坦化する必要があります。LINQ to XMLを使用してテキストノードと要素ノードで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> 

私はXMLにLINQを使用することを好むが、content要素ノードの隣の子供のテキストノードが今、すべての異なるタスク作る実現します。

私が持っていたもう一つのアイデアはそして、それに応じて属性styleCodeを更新し、その直後に子ノードと開口部<content></content>を閉じる挿入することによって、各段階でInnerXmlプロパティを組み合わせることが、正規表現を使用し、古いノードを削除することでした。私はこの考え方にも成功していません。

すべてのアイデア、解決策は非常に高く評価されています。

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'でそれらを挿入し、すべて削除された古い(既に平坦化された)ノードの後に​​挿入しました。 しかし、あなたの考えはうまく働いているようです。 ありがとう! –

関連する問題