简体   繁体   English

查找和替换XML文件

[英]Find and Replace through XML files

I have a lot of XML files that need to be edited. 我有很多需要编辑的XML文件。 I need to find all instances with: Example 我需要使用以下命令查找所有实例:

<Btn> 
    <sText>Hold</sText>

and add a field before it 并在其前面添加一个字段

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

I have read the using regex on XML is not advisable. 我读过不建议在XML上使用正则表达式。 What would be the best way to achieve a large one time operation for multiple files for something like this? 对这样的多个文件进行一次大型操作的最佳方法是什么?

For regex I tried but with no luck to just start out with searching for the needed fields. 对于正则表达式,我尝试过但没有运气,只是从搜索所需字段开始。

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

Using editors like notepad++,Brackets currently to edit files. 使用记事本++之类的编辑器,当前使用Brackets编辑文件。 Any suggestions on doing a large one time one time operation would be greatly appreciated. 任何建议进行一次大的一次性操作将不胜感激。 Doing the changes by hand in the GUI to hundreds of configs is not desirable.Just looking for an alternative route to save sanity. 在GUI中手动对数百个配置进行更改是不理想的,只是在寻找一种替代方法来节省理智。

I have an XSL approach you might like to try. 我有您可能想尝试的XSL方法。 XSL is great for transforming XML documents of one kind into another (amongst other things). XSL非常适合将一种XML文档转换为另一种XML文档。

As I understand it, you need to find each instance of Btn and copy it to a new instance before its current location. 据我了解,您需要找到Btn的每个实例并将其复制到当前位置之前的新实例。

With this in mind, here's how I got it to work. 考虑到这一点,这就是我如何使其工作的方式。

Test.xml file: 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>

Note the use of the stylesheet reference, you would need to add this to the documents you wish to edit. 注意使用样式表引用,您需要将其添加到要编辑的文档中。

Test.xslt file: 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>

The output should look like this: 输出应如下所示:

<?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>

The newly duplicated instances of your Btn nodes are named NewBtn in this example. 在本示例中,您的Btn节点的新复制实例称为NewBtn。

Note that I've changed/added some elements here (Output, Something) in order to get valid XML. 请注意,为了获得有效的XML,我已经在此处更改/添加了一些元素(输出,某些内容)。

I hope that helps! 希望对您有所帮助!

You can create an object for your XML document. 您可以为XML文档创建一个对象。 From there you can traverse through all of its nodes, find what you are looking for and add them to a list. 从那里,您可以遍历其所有节点,找到所需的内容并将它们添加到列表中。 When you already have the list, you can then write your logic for inserting the nodes that you want. 在拥有列表之后,您就可以编写用于插入所需节点的逻辑。 I'm using LINQ. 我正在使用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;
    }
}

You can try to solve it without regular expressions. 您可以尝试不使用正则表达式来解决它。 For example you can use XmlReader and XmlWriter 例如,您可以使用XmlReaderXmlWriter

  • Read one row with XmlReader 用XmlReader读一行
  • Check for your condition 检查您的状况
  • Skip/modify row 跳过/修改行
  • Write row with XmlWriter 用XmlWriter写行

It's the most memory and CPU efficient solution since you don't need to load whole file to memory and XML Writer/Reader in C# are pretty fast compared to XDocument or other fancy xml parsers. 这是内存和CPU效率最高的解决方案,因为您不需要将整个文件加载到内存中,并且与XDocument或其他高级xml解析器相比,C#中的XML Writer / Reader相当快。 Moreover it's simple so you need to mess with regexes and can contain any complicated logic you will need. 此外,它很简单,因此您需要使用正则表达式,并且可以包含所需的任何复杂逻辑。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM