通过XML文件查找和替换

时间:2015-02-26 22:44:07

标签: c# regex xml

我有很多需要编辑的XML文件。 我需要找到所有实例: 实施例

<Btn> 
    <sText>Hold</sText>

并在其前面添加一个字段

  <Btn>//star of new fields
      <sText>Tools</sText>    
      *rest of fields*     
  </Btn> //end of added fields  
  <Btn> //start of original search
      <sText>Hold</sText>

我已经读过在XML上使用正则表达式是不可取的。对于像这样的事情,为多个文件实现大型一次性操作的最佳方法是什么?

对于正则表达式,我试过但没有运气,只是开始搜索所需的字段。

/<Btn>(.*?(\n))+.*?<sText>Hold</sText>/im

使用notepad ++等编辑器,Brackets目前正在编辑文件。任何关于做一次大一次操作的建议都将不胜感激。在GUI中手动更改数百个配置是不可取的。只需寻找另一条路线来保存理智。

3 个答案:

答案 0 :(得分:1)

我有一种您可能想尝试的XSL方法。 XSL非常适合将一种XML文档转换为另一种文档(等等)。

据我了解,您需要找到Btn的每个实例并将其复制到当前位置之前的新实例。

考虑到这一点,我就是这样做的。

Test.xml文件:

<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="Test.xslt"?>

<Something>
  <Btn>
    <sText>Hold</sText>
    <Another>Foo</Another>
  </Btn>
  <Btn>
    <sText>Hold</sText>
  </Btn>
  <Btn>
    <sText>Hold</sText>
  </Btn>
</Something>

请注意使用样式表引用,您需要将其添加到要编辑的文档中。

Test.xslt文件:

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

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

  <xsl:template match="/">
    <xsl:element name="Output">
      <xsl:apply-templates select="//Btn" />
    </xsl:element>
  </xsl:template>

  <xsl:template match="Btn">
    <xsl:element name="NewBtn">
      <xsl:copy-of select="current()/*" />
    </xsl:element>
    <xsl:element name="Btn">
      <xsl:copy-of select="current()/*" />
    </xsl:element>
  </xsl:template>

</xsl:stylesheet>

输出应如下所示:

<?xml version="1.0" encoding="utf-8"?>
<Output>
  <NewBtn>
    <sText>Hold</sText>
    <Another>Foo</Another>
  </NewBtn>
  <Btn>
    <sText>Hold</sText>
    <Another>Foo</Another>
  </Btn>
  <NewBtn>
    <sText>Hold</sText>
  </NewBtn>
  <Btn>
    <sText>Hold</sText>
  </Btn>
  <NewBtn>
    <sText>Hold</sText>
  </NewBtn>
  <Btn>
    <sText>Hold</sText>
  </Btn>
</Output>

在此示例中,新复制的Btn节点实例名为NewBtn。

请注意,为了获得有效的XML,我在这里更改/添加了一些元素(Output,Something)。

我希望有所帮助!

答案 1 :(得分:1)

您可以为XML文档创建对象。从那里,您可以遍历其所有节点,找到您要查找的内容并将其添加到列表中。当您已有列表时,可以编写用于插入所需节点的逻辑。我正在使用LINQ。

public class Program
{
    static void Main(string[] args)
    {
        XDocument doc = XDocument.Load("YourXmlFile.xml");

        RootElement root = new RootElement(doc.Elements().FirstOrDefault());

        foreach (XElement item in root.GetInstances())
        {
            //--Your logic for adding the fields you want
        }

        Console.ReadLine();
    }
}

public class RootElement
{
    public List<XElement> childElements { get; set; }

    public RootElement(XElement xElement)
    {
        childElements = new List<XElement>();

        foreach (XElement e in xElement.Elements())
        {
            childElements.Add(e);
        }
    }

    public List<XElement> GetInstances()
    {
        List<XElement> instances = new List<XElement>();
        foreach (XElement item in childElements)
        {
            if (item.Name == "Btn")
            {
                IEnumerable<XElement> elements = item.Elements();
                XElement child = elements.FirstOrDefault(x => x.Name == "sText");

                if (child != null)
                {
                    if (child.Value == "Hold")
                    {
                        instances.Add(item);
                    }
                }
            }
        }

        return instances;
    }
}

答案 2 :(得分:-1)

您可以尝试在没有正则表达式的情况下解决它。例如,您可以使用XmlReaderXmlWriter

  • 使用XmlReader
  • 读取一行
  • 检查您的情况
  • 跳过/修改行
  • 使用XmlWriter编写行

这是最节省内存和CPU的解决方案,因为您不需要将整个文件加载到内存中,而且与XDocument或其他花哨的xml解析器相比,C#中的XML Writer / Reader非常快。此外,它很简单,因此您需要使用正则表达式,并且可以包含您需要的任何复杂逻辑。