如何拆分这个XmlDocument?

时间:2012-01-18 22:14:52

标签: c# xml

这里不是一个大的XML专家...说我有一个更大的文档的Xml节点,看起来像这样:

<TopLevel>
   <Element1>...</Element1>
   <Element2>...</Element2>
   <Element3>
      <Sub1>abc</Sub1>
      <Sub2>def</Sub2>
   </Element3>
   <Element3>
      <Sub1>ghi</Sub1>
      <Sub2>jkl</Sub2>
   </Element3>
   <Element3>
      <Sub1>mno</Sub1>
      <Sub2>pqr</Sub2>
   </Element3>
</TopLevel>

(Element3可以重复无限次) 我想结束三个节点,如下所示:

<TopLevel>
   <Element1>...</Element1>
   <Element2>...</Element2>
   <Element3>
      <Sub1>abc</Sub1>
      <Sub2>def</Sub2>
   </Element3>
</TopLevel>
<TopLevel>
   <Element1>...</Element1>
   <Element2>...</Element2>
   <Element3>
      <Sub1>ghi</Sub1>
      <Sub2>jkl</Sub2>
   </Element3>
</TopLevel>
<TopLevel>
   <Element1>...</Element1>
   <Element2>...</Element2>
   <Element3>
      <Sub1>mno</Sub1>
      <Sub2>pqr</Sub2>
   </Element3>
</TopLevel>

如果我知道Element3只能重复两次我只是克隆节点,从原始节点中删除第一个实例,从克隆节点和InsertAfter中删除第二个实例,但我不知道如何做到未知数量的元素......

谢谢!

3 个答案:

答案 0 :(得分:2)

如果XSLT是您的选项,那么以下样式表

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="xml" encoding="utf-8" indent="yes"/>

    <xsl:template match="node()|@*" name="identity">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="/TopLevel">
        <root>
            <xsl:apply-templates select="Element3"/>
        </root>
    </xsl:template>

    <xsl:template match="Element3">
        <TopLevel>
            <xsl:apply-templates select="../Element1|../Element2"/>
            <xsl:call-template name="identity"/>
        </TopLevel>
    </xsl:template>

</xsl:stylesheet>

产生以下输出(我格式化):

<root>
    <TopLevel>
        <Element1>...</Element1>
        <Element2>...</Element2>
        <Element3>
      <Sub1>abc</Sub1>
      <Sub2>def</Sub2>
        </Element3>
    </TopLevel>
    <TopLevel>
        <Element1>...</Element1>
        <Element2>...</Element2>
        <Element3>
      <Sub1>ghi</Sub1>
      <Sub2>jkl</Sub2>
        </Element3>
    </TopLevel>
    <TopLevel>
        <Element1>...</Element1>
        <Element2>...</Element2>
        <Element3>
      <Sub1>...</Sub1>
      <Sub2>...</Sub2>
        </Element3>
    </TopLevel>
</root>

您提供的输出是文档片段;我添加了一个root元素,以便它可以作为常规文档加载。但是XSLT也会在没有根元素的情况下发出这个。

答案 1 :(得分:1)

XML标准只允许单个顶级节点,因此您需要一个围绕所有<TopLevel>的包装器。取决于您的输出消耗量可能或不重要。

XDocument input; //Fill this in somehow
XElement top = input.Element("TopLevel");
XElement elem1 = top.Element("Element1");
XElement elem2 = top.Element("Element2");
XDocument output = new XDocument(); //You may need to do additional initialization here
foreach (XElement elem3 in top.Elements("Element3");
{
    output.Add(new XElement("TopLevel", elem1, elem2, elem3));
}

自从我生成输出文件以来已经有一段时间了,所以如果我的语法不是100%正确,我很抱歉。

答案 2 :(得分:0)

这样的东西?

string fromXml = 
@"
    <TopLevel>
        <Element1>...</Element1>
        <Element2>...</Element2>
        <Element3>
            <Sub1>abc</Sub1>
            <Sub2>def</Sub2>
        </Element3>
        <Element3>
            <Sub1>ghi</Sub1>
            <Sub2>jkl</Sub2>
        </Element3>
        <Element3>
            <Sub1>...</Sub1>
            <Sub2>...</Sub2>
        </Element3>
    </TopLevel>
";

XElement from = XElement.Parse(fromXml);
XElement root = new XElement("Root");
foreach (var node in from.Descendants("Element3"))
{
    XElement toplevel = new XElement("TopLevel");
    toplevel.Add(from.Element("Element1"));
    toplevel.Add(from.Element("Element2"));
    toplevel.Add(node);
    root.Add(toplevel);
}
var final = root.Nodes().Aggregate("",((s,n)=>s+=n.ToString()+"\n"));