1

考虑以下 xml:

<div>
   <a href="http://www.google.com/">This is:</a>
   <p>A test... <b>1</b><i>2</i><u>3</u></p>
   <p>This too</p>
   Finished.
</div>

此 xml 的内容位于System.Xml.XmlDocument实例中。我需要替换所有p元素并在每个段落元素之后添加一个中断。我编写了以下代码:

var pElement = xmlDocument.SelectSingleNode("//p");
while (pElement != null)
{
    var textNode = xmlDocument.CreateTextNode("");
    foreach (XmlNode child in pElement.ChildNodes)
    {
        textNode.AppendChild(child);
    }    
    textNode.AppendChild(xmlDocument.CreateElement("br"));
    pElement.ParentNode.ReplaceChild(pElement, textNode);
    pElement = xmlDocument.SelectSingleNode("//p");
}

我正在创建一个空节点并将每个段落节点的子节点添加到它。不幸的是,这不起作用:文本节点不能包含元素。

任何想法如何实施此替换?

4

3 回答 3

2

看起来我找到了使用该InsertAfter方法的解决方案:

var pElement = xmlDocument.SelectSingleNode("//p");

while (pElement != null)
{    
    //store position where new elements need to be added
    var position = pElement;

    while(pElement.FirstChild != null)
    {
        var child = pElement.FirstChild;
        position.ParentNode.InsertAfter(child, position);

        //store the added child as position for next child
        position = child;
    }

    //add break
    position.ParentNode.InsertAfter(xmlDocument.CreateElement("br"), position);

    //remove empty p
    pElement.ParentNode.RemoveChild(pElement);

    //select next p
    pElement = xmlDocument.SelectSingleNode("//p");
}

思路如下:

  1. 查看所有p节点。
  2. 循环遍历所有子节点p
  3. 将它们添加到正确的位置。
  4. 在每个p节点之后添加一个中断。
  5. 移除p元素。

这个位置很难找到。第一个子节点需要p使用InsertAfterwithp作为位置元素添加到父节点。但是下一个孩子需要在之前添加的孩子之后添加。解决方法:保存它的位置并使用它。

注意:在集合上使用for each迭代器是pElement.ChildNodes行不通的,因为在移动一半节点后,迭代器决定它完成了。看起来它使用某种计数而不是对象集合。

于 2013-02-25T18:30:04.140 回答
0

如果我了解您要实现的目标,您可以尝试以下操作:

foreach (XmlNode node in doc.SelectNodes("//p"))
{
    node.ParentNode.InsertAfter(doc.CreateElement("br"), node);
}

如果我没有理解正确,也许您可​​以发布您想要实现的输出。

于 2013-02-25T16:35:40.440 回答
0

修改内存中的对象是有问题的 - 请参阅此处XmlDocument的类似问题。

最简单的方法是使用 XSLT:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="p">
    <xsl:copy-of select="node()"/>
    <br/>
  </xsl:template>

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

</xsl:stylesheet>

然后你可以将它应用到你XmlDocument使用XslCompiledTransform生成字符串或输出 XML 流的类中。

于 2013-02-25T16:29:28.067 回答