【问题标题】:在匹配一些文本后插入一个新行和一些文本c#
【发布时间】:2022-01-23 15:07:17
【问题描述】:

我有一个 txt 文件,其中包含

<?xml version="1.0" blablabla ..etc>
  <uses-permission ~~~~~~ ..etc>
  <application ~~~some of words i dont know it and changes from file to another file~~~ >
  </application>
</manifest>

我需要在新行的特定位置添加“Hello World”,最终文件将如下所示

<?xml version="1.0" blablabla ..etc>
  <uses-permission ~~~~~~ ..etc>
Hello World
  <application ~~~some of words i dont know it and changes from file to another file~~~ >
Hello World
  </application>
</manifest>

请问,我如何在 c# 中做到这一点?而且我不知道行中的某些单词,我将在其后添加“Hello World”,因此我需要先检测行,例如第 195 行中的“

【问题讨论】:

  • 或将 XML 文件反序列化/序列化为更安全的方法
  • @Dai 你的意思是正则表达式:正则表达式?你能帮我写代码吗因为我是菜鸟
  • @user16535021 以便我更好地为您量身定制回复,您的计算机科学或软件工程教育水平如何?
  • ......@Dai 404
  • 请发布您的整个源文本/XML 文件不要对其进行任何更改。它是有效(结构正确)的 XML 文件还是 tag-soup 文件?

标签: c#


【解决方案1】:

虽然(一般来说)Android manifest文件中元素的顺序does not matter, there are 2 documented exceptions where order does matter, and unfortunately for us the 2nd exception applies to us

  1. &lt;activity-alias&gt; 元素必须跟在作为别名的 &lt;activity&gt; 之后。
  2. &lt;application&gt; 元素必须是 &lt;manifest&gt; 元素内的最后一个元素。

所以鸟瞰图是:

  1. 将 Android 应用清单 XML 文件加载到 XDocument 对象中。
  2. 要添加a new &lt;uses-permission&gt; elementa new &lt;permission&gt; element,您需要添加为根&lt;manifest&gt; 元素的直接子元素,但位于&lt;application&gt; 元素之前
  3. 要添加 a new &lt;service&gt; element,请将其作为新的直接子元素附加到 &lt;application&gt;

像这样:

using System.Linq;
using System.Xml.Linq;

public static class Program
{
    public static Int32 Main( String[] args )
    {
        const String FILE_NAME = "MyManifest.xml";
        
        if( !File.Exists( FILE_NAME ) )
        {
            Console.WriteLine( "Couldn't find \"" + FILE_NAME + "\"." );
            return 1;
        }

        // Load the XML from disk:
        String manifestXmlText = File.ReadAllText( FILE_NAME  );
        
        // Parse it into an an XDocument:
        XDocument manifestXmlDocument = XDocument.Parse( manifestXmlText );
        
        // Add the new elements:
        AddElementsToAndroidManifest( manifestXmlDocument );

        // Then save the updated XML document back to disk, overwriting the original file:
        using( FileStream fs = File.OpenWrite( FILE_NAME ) )
        {
            manifestXmlDocument.Save( fs );
        }

        return 0;
    }
    
    private static void AddElementsToAndroidManifest( XDocument manifestXmlDocument )
    {
        XElement   manifestEl    = manifestXmlDocument.Root                                         ?? throw new InvalidOperationException( "Couldn't find root <manifest> element." ) ;
        XElement   applicationEl = manifestXmlDocument.Descendants("application").SingleOrDefault() ?? throw new InvalidOperationException( "Couldn't find <application> element." ); // Get the <application> element.
        XNamespace androidNS     = manifestEl.GetNamespaceOfPrefix(prefix: "android")               ?? throw new InvalidOperationException( "Couldn't find xmlns:android" );; // "http://schemas.android.com/apk/res/android"

        {
            // <uses-permission>'s attributes use XML namespaces, so this complicates things:
            // https://stackoverflow.com/questions/4985974/xelement-namespaces-how-to
            // https://docs.microsoft.com/en-us/dotnet/standard/linq/namespaces-overview
            // https://stackoverflow.com/questions/2874422/how-to-set-the-default-xml-namespace-for-an-xdocument
            // https://stackoverflow.com/questions/1338517/how-can-i-write-xml-with-a-namespace-and-prefix-with-xelement

            XElement newUsesPermissionEl = new XElement( "uses-permission",
                new XAttribute( androidNS + "name"         , "bar"), 
                new XAttribute( androidNS + "maxSdkVersion", "123")
            );

            applicationEl.AddBeforeSelf( newUsesPermissionEl ); // Add the new <uses-permission> element as a preceding sibling of <application>.
        }

        {
            // <service>:

            XElement newServiceEl = new XElement( "service",
                new XAttribute( androidNS + "description", "Some day, some day, Some day, Dominion; Some day, some day, Some say prayers; I say mine"), 
                new XAttribute( androidNS + "name"       , "Dominion service"),
                new XAttribute( androidNS + "label"      , "Andrew Eldritch fanclub <3"),
            );

            applicationEl.Add( newServiceEl ); // Add the new <service> element as an immediately child of <application>.
        }
    }
}

所以将the official example Manifest XML 作为输入(在MyManifest.xml 中)...:

<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="com.example.myapp">
  <!-- Beware that these values are overridden by the build.gradle file -->
  <uses-sdk android:minSdkVersion="15" android:targetSdkVersion="26" />
  <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:roundIcon="@mipmap/ic_launcher_round" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme">
    <!-- This name is resolved to com.example.myapp.MainActivity
             based upon the package attribute -->
    <activity android:name=".MainActivity">
      <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
      </intent-filter>
    </activity>
    <activity android:name=".DisplayMessageActivity" android:parentActivityName=".MainActivity" />
  </application>
</manifest>

...我得到这个输出:

<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="com.example.myapp">
  <!-- Beware that these values are overridden by the build.gradle file -->
  <uses-sdk android:minSdkVersion="15" android:targetSdkVersion="26" />
  <uses-permission android:name="bar" android:maxSdkVersion="123" />
  <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:roundIcon="@mipmap/ic_launcher_round" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme">
    <!-- This name is resolved to com.example.myapp.MainActivity
             based upon the package attribute -->
    <activity android:name=".MainActivity">
      <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
      </intent-filter>
    </activity>
    <activity android:name=".DisplayMessageActivity" android:parentActivityName=".MainActivity" />
    <service android:description="Some day, some day, Some day, Dominion; Some day, some day, Some say prayers; I say mine" android:name="Dominion service" android:label="Andrew Eldritch fanclub &lt;3" />
  </application>
</manifest>

如您所见,&lt;service&gt;&lt;uses-permission&gt; 元素已插入到正确的位置。

【讨论】:

  • @user16535021 用我最好的 Gordon 专员的声音:这是你想要的,但这是你应得的吗?
  • 兄弟,我使用 .NET Framework,那么您应该使用 FileStream,因为 System.IO 不提供 File.ReadAllTextAsync 方法。
  • @user16535021 您在帖子中没有提到这一点。但我敢肯定你可以很好地使用非异步方法。
  • @Dia 你能修复GetNamespaceOfPrefix 错误:XDocument 不包含“GetNamespaceOfPrefix”的定义并且没有可访问的扩展方法....
  • @user16535021 我的错。请尝试我的更新代码。
猜你喜欢
  • 2019-08-24
  • 2013-07-02
  • 1970-01-01
  • 1970-01-01
  • 2016-06-03
  • 1970-01-01
  • 1970-01-01
  • 2014-10-24
  • 1970-01-01
相关资源
最近更新 更多