c# - 使用 LINQ to XML 使用文本和元素节点展平 xml

标签 c# xml algorithm linq 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>

我更喜欢使用 LINQ to XML,但要意识到 content 旁边的子文本节点元素节点现在使所有任务变得不同。

我的另一个想法是使用正则表达式在每一步中通过插入结束 </content> 来组合innerxml。在子节点之前并打开 <content>紧随其后,相应地更新 styleCode 属性,然后 AddBeforeSelf并删除旧节点。我这个想法也没有成功。

非常感谢任何想法、解决方案。

除了组合和扁平化之外 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();
}

最佳答案

您可以递归地执行此操作 - 从一个节点到另一个节点收集样式,当涉及到文本时,将其包装到包含迄今为止找到的所有标签的内容标签。代码如下:

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);
            }
        }
    }
}

关于c# - 使用 LINQ to XML 使用文本和元素节点展平 xml,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39370407/

相关文章:

c# - 调整数组大小以丢失空值

javascript - 在前端抓取从 Django 发送的文件

xml - XSLT 命名空间更改

android - 对话框颜色选择器仅显示购买的颜色

c# - 从 3d 空间中的一组点移动到具有最短可能累积距离的另一组点

performance - Clojure 中的 Takeuchi 数字(性能)

c# - Windows Embedded 中的远程调试

c# - 如何使用 Linq2Sql 模拟 "In"

image - 定向 gabor 滤波器的盒式滤波器近似

c# - Windows Phone 8.1 页面导航