2

私は翻訳をXMLに入れなければならないプロジェクトに取り組んでいます。これで、xml変換ファイルが自動生成されますが、プロジェクトの私の部分では生成されません。私と彼らは、生成されたXMLを共有する必要があります。

したがって、XMLの一部を「メイン」XMLに入力すると、ファイルが再生成されるときに上書きされます。現在の解決策は、翻訳を含む別のファイルを保持し、それを毎回「メイン」のXMLファイルにコピーして貼り付けることです。

これを自動的に行う方法はありますか?xmlオプションを試しましたが、VisualStudioIncludeがそれを認識または使用しません。

「メイン」のXMLで何らかのプレースホルダーを生成することを考えましたが、VisualStudioは「どういうわけか」プレースホルダーを別のファイルのXMLに置き換えます。

何か案は?

4

5 に答える 5

3

ここで説明するENTITYセクションを含むxmlファイルを含める方法があります。.Net XmlReaderが自動的に実行しない場合は、ルートファイルを読み取る前に、XmlResolverを自分で実装し、XmlReaderSettingsに設定する必要があります。ResolveUriをオーバーライドするだけで十分です。

たとえば、xmlが次のようになっていると仮定します。

root.xml:

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE root [
  <!ENTITY generatedXML SYSTEM "generated.xml">
  <!ENTITY generatedXML2 SYSTEM "pack://application:,,,/generated2.xml">
]>
<root>
  &generatedXML;
  &generatedXML2;
  <extraContent>
    <extraValue Name="xa" Value="1"/>
    <extraValue Name="xb" Value="1"/>
    <extraValue Name="xc" Value="1"/>
    <extraValue Name="xd" Value="1"/>
  </extraContent>
</root>

Generated.xmlおよびgenerated2.xml:

<?xml version="1.0" encoding="utf-8" ?>
<generatedContent>
  <generatedValue Name="a" Value="1"/>
  <generatedValue Name="b" Value="2"/>
  <generatedValue Name="c" Value="3"/>
  <generatedValue Name="d" Value="4"/>
</generatedContent>

「generated.xml」はルートxmlの隣にあり、「generated2.xml」はアプリケーションアセンブリの1つの別の場所にあり、「BuildAction=Resource」とマークされています。次に、次のようなXmlResolverを記述できます。

using System;
using System.IO;
using System.IO.Packaging;
using System.Net;
using System.Xml;

namespace XmlResolution
{
    class XmlResourceResolver : XmlResolver
    {
        private static readonly string FileScheme = "file";
        private static readonly string PackScheme = PackUriHelper.UriSchemePack;
        private ICredentials credentials;

        public override ICredentials Credentials
        {
            set { this.credentials = value; }
        }

        public override object GetEntity(Uri absoluteUri, string role, Type ofObjectToReturn)
        {
            if (absoluteUri.Scheme == FileScheme)
            {
                return File.OpenRead(absoluteUri.LocalPath);
            }
            else if (absoluteUri.Scheme == PackScheme)
            {
                return System.Windows.Application.GetResourceStream(absoluteUri).Stream;
            }

            return null;
        }
    }
}

そして最後に、次のようにxmlを読み取ることができます。

    static void Main(string[] args)
    {
        var settings = new XmlReaderSettings
        {
            DtdProcessing = DtdProcessing.Parse,
            XmlResolver = new XmlResourceResolver()
        };

        using (var reader = XmlReader.Create("root.xml", settings))
        {
            var element = XElement.Load(reader);

            var nameValuePairs = from content in element.Elements()
                                 from value in content.Elements()
                                 select new
                                 {
                                     Name = value.Attribute("Name"),
                                     Value = int.Parse(value.Attribute("Value").Value)
                                 };

            foreach (var pair in nameValuePairs)
            {
                Console.WriteLine(pair.Name + " " + pair.Value);
            }
        }
    }
于 2012-09-29T22:41:02.323 に答える
1

次のようにすることができます(どのように読んでいるかわからないので、XmlDocumentを使用できると仮定します。そうでない場合は、XmlDocumentを必要に応じて変換できます)。

ArrayList xmlNodes;
XmlNode newNode;

XmlDocument xmlDoc = new XmlDocument();
XmlDocument toInclude = new XmlDocument();

xmlDoc.Load("myFile.xml");
toInclude.Load("toInclude.xml");

xmlNodes = new ArrayList();

foreach (XmlElement ele in xmlDoc.GetElementsByTagName("toReplace"))
{
    xmlNodes.Add(ele);
}

foreach (XmlElement ele in xmlNodes)
{
    ele.ParentNode.ReplaceChild(xmlDoc.ImportNode(toInclude.DocumentElement, true), ele);
}

これにより、タグがtoInclude.xmlファイルのルートノードに置き換えられます。

于 2012-09-28T15:53:46.427 に答える
1

DataSetオブジェクトも使用できます。

    XmlTextReader readerOne = new XmlTextReader("C:\\generated.xml");
    XmlTextReader readerTwo = new XmlTextReader("C:\\your-file.xml");

    DataSet dsOne = new DataSet();
    dsOne.ReadXml(readerOne);

    DataSet dsTwo = new DataSet();
    dsTwo.ReadXml(readerTwo);

    dsOne.Merge(dsTwo);
    dsOne.WriteXml("C:\\CompleteResource.xml");
    Console.WriteLine("Merge completed");
于 2012-09-28T22:00:18.260 に答える
1

私が思ったOPを読んで:Visual Studioプロジェクト内の任意のxmlファイル(このファイルを変換するためのXSLファイル)に関連付けることができるのは素晴らしいことではないでしょうか。この変換の結果は、*。xaml.csが* .xamlの下に表示されるように、元のxmlファイルの下にサブアイテムとして表示されます。また、プロパティを使用して、この新しいxmlファイルに任意のビルドアクションを割り当てることができます。

これは現在は不可能ですが、別のより一般的な前処理手法であるT4が存在します。これは、「私たちの」xmlフラグメントを「彼らの」生成されたxmlファイルに挿入するためにそれを使用する方法の説明です。

1)「彼らの」生成されたxmlファイルがaaa.xmlという名前でプロジェクトに含まれていると仮定しましょう。

例: aaa.xml

<?xml version="1.0" encoding="utf-8"?>
<abc>
  <data a="1"/>
  <data a="2"/>
  <placeholderForTranslations/>
  <data>ccc</data>
</abc>

ここで、placeholderForTranslations要素は「our」フラグメントで置き換える必要があります。

2)placeholderForTranslationsを「our」フラグメントに置き換えることでaaa.xmlを変換するaaa.xsltファイルをプロジェクトに追加しましょう。

aaa.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:strip-space elements="*"/>

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

  <xsl:template match="placeholderForTranslations">
    <translations>
      <trans orig="aaa" translated="AAA"/>
    </translations>
  </xsl:template>

</xsl:stylesheet>

ここでの最初のxsl:templateは、デフォルトでは、変換エンジンが入力ファイルのノードを通過するときに、それらをそのまま出力にコピーすることを示しています。2番目のテンプレートは、placeholderForTranslations要素が検出された場合に、ここでテンプレートに埋め込まれたxmlのフラグメントを使用してplaceholderForTranslations要素を置き換えることを示しています。実際、必要に応じて、このフラグメントが別のファイルからも読み取られるように、*。ttファイル(以下を参照)を変更することができます。

3)aaa1.tt--t4コードプリプロセッサフ​​ァイルをプロジェクトに追加しましょう。

aaa1.tt

<#@ template debug="false" hostspecific="true" language="C#" #>
<#@ output extension=".xml" #>
<#@ assembly name="System.Xml" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Xml" #>
<#@ import namespace="System.IO" #>
<#@ import namespace="System.Xml.Xsl" #>
<#
    string origXmlPath = Host.ResolvePath("aaa.xml");
    string transformPath = Host.ResolvePath("aaa.xslt");

    XslCompiledTransform transform = new XslCompiledTransform();
    transform.Load(transformPath);
    MemoryStream stream = new MemoryStream();
    transform.Transform(origXmlPath, null, stream);
    byte[] generated = stream.ToArray();
    string generatedString = Encoding.UTF8.GetString(generated);
#>
<#= generatedString #>

<#と#>の間に、aaa.xmlとaaa.xsltへのフルパスを見つけてaaa.xslt変換をaaa.xmlファイルに適用し、その結果をgeneratedString変数に入れるC#コードの一部を見ることができます。次に、<#= GeneratedString#>を使用して、generatedStringのコンテンツが出力ファイルに挿入されます。

これらの手順を実行すると、Visual Studioでのaaa1.ttの最初の保存時に、ファイルaaa1.xmlがaaa1.ttのサブアイテムとして作成されます。プロパティを介してこのファイルに、「埋め込みリソース」などのビルドアクションを割り当てることができます。aaa.ttを右クリックして[カスタムツールの実行]を選択することにより、いつでもaaa1.xmlの再生成を強制することができます。また、ソリューションを構築するときに常に再生成されます。

このアプローチの利点は、マージされたファイルがアプリケーションの実行時ではなく、コンパイル時に生成されることだと思いました。そのため、開発中にファイルを視覚的に検査できます。

于 2012-10-02T15:30:35.083 に答える
0

次のxmlファイルがあると仮定すると、別の方法があります。

<?xml version="1.0" encoding="utf-8"?>
<root>
  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
    <xsd:element name="root" msdata:IsDataSet="true">
      <xsd:complexType>
        <xsd:choice maxOccurs="unbounded">
          <xsd:element name="data">
            <xsd:complexType>
              <xsd:sequence>
                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
              </xsd:sequence>
              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
              <xsd:attribute ref="xml:space" />
            </xsd:complexType>
          </xsd:element>
          <xsd:element name="resheader">
            <xsd:complexType>
              <xsd:sequence>
                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
              </xsd:sequence>
              <xsd:attribute name="name" type="xsd:string" use="required" />
            </xsd:complexType>
          </xsd:element>
        </xsd:choice>
      </xsd:complexType>
    </xsd:element>
  </xsd:schema>
  <resheader name="resmimetype">
    <value>text/microsoft-resx</value>
  </resheader>
  <resheader name="version">
    <value>2.0</value>
  </resheader>
  <resheader name="reader">
    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
  </resheader>
  <resheader name="writer">
    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
  </resheader>
  <data name="ApplicationMainWindow_Button_RunWizard" xml:space="preserve">
    <value>Ordenar Café</value>
  </data>
  <data name="ApplicationMainWindow_OrderCancelled" xml:space="preserve">
    <value>Orden Cancelada</value>
  </data>
  <data name="ApplicationMainWindow_OrderComplete_Formatted" xml:space="preserve">
    <value>El costo de la tasa de café es de {0}, gracias.</value>
  </data>
</root>

そして、あなたは以下とマージしたいです:

<?xml version="1.0" encoding="utf-8" ?>
<root>
  <data name="ApplicationMainWindow_Title" xml:space="preserve">
    <value>Café de casa</value>
  </data>
  <data name="BeanType_Breakfast" xml:space="preserve">
    <value>Grand Aroma</value>
  </data>
</root>

次に、次のようにコーディングできます。

public class XmlManager
{
    private XDocument _document1;
    private XDocument _document2;
    private string _autogenerated;
    private string _manual;
    private string _target;
    public XmlManager()
    {
        Initialize();
    }

    private void Initialize()
    {
        _autogenerated = @"c:\AutogeneratedResource.xml";
        _manual = @"c:\ManualResource.xml";

        XmlDocument doc = new XmlDocument();
        doc.Load(_autogenerated);
        _document1 = XDocument.Parse(doc.InnerXml);

        doc.Load(_manual);
        _document2 = XDocument.Parse(doc.InnerXml);

        _target = @"c:\Target.xml";
    }

    public void Save()
    {
        if (_document2.Root != null)
        {
            IEnumerable<XElement> elements = _document2.Root.Elements("data");
            if (_document1.Root != null)
                _document1.Root.Add(elements);

            _document1.Save(new StreamWriter(_target));
        }
    }
}
于 2012-10-06T06:21:59.010 に答える