2017-07-21 8 views
2

私は、XMLファイルを受け取り、タグからxmlns属性を削除し、ルートタグにこれらの属性の接頭辞を設定し、代わりにこれらの接頭辞を代わりに使用するC#でユーティリティを作成しようとしています。xmlns名前空間の属性を接頭辞に置き換えるにはどうすればよいですか?

ソースXMLファイル:

<?xml version="1.0" encoding="utf-8"?> 
<Main version="1.0" xmlns="urn:root:v1"> 
    <Report> 
     <Title>Some Value</Title> 
    </Report> 
    <Content> 
     <Address> 
      <CountryName xmlns="urn:location:v2">Australia</CountryName> 
     </Address> 
    </Content> 
</Main> 

ターゲットXMLファイル:

<?xml version="1.0" encoding="utf-8"?> 
<root:Main version="1.0" xmlns:root="urn:root:v1" xmlns:loc="urn:location:v2"> 
    <root:Report> 
     <root:Title>Some Value</root:Title> 
    </root:Report> 
    <root:Content> 
     <root:Address> 
      <loc:CountryName>Australia</loc:CountryName> 
     </root:Address> 
    </root:Content> 
</root:Main> 

私は次のコードでそこに道の一部を得ることができました。すべてのタグをルートプレフィックスのない属性に置き換え、xmlns属性をルートタグに追加しましたが、代わりにCountryNameタグからxmlns属性を削除し、代わりにプレフィックスを使用していません。

XDocument doc = XDocument.Load(@"C:\Temp\Source.xml"); 

var content = XElement.Parse(doc.ToString()); 

content.Attributes("xmlns").Remove(); 

content.Add(new XAttribute(XNamespace.Xmlns + "root", "urn:root:v1")); 
content.Add(new XAttribute(XNamespace.Xmlns + "loc", "urn:location:v2")); 

foreach (var node in doc.Root.Descendants().Where(n => n.Name.NamespaceName == "urn:location:v2")) 
{ 
    node.Attribute("xmlns").Remove(); 
    node.Add(new XAttribute(XNamespace.Xmlns + "loc", "urn:location:v2")); 
} 

content.Save(@"C:\Temp\Target.xml"); 

ご協力いただければ幸いです。ありがとうございます!

+0

docの子孫ノードから属性を削除しようとしましたが、内容を変更しなかったファイルに保存してください。ですから、 'doc.Root.Descendants()'を 'content.Descendants()'に変更するだけです。 –

+0

@GeorgeAlexandriaありがとうございます。私はまだ 'xmlns:loc =" urn:location:v2 "'を取り除きたいと思っています。何か案は? 'オーストラリア ' – Acewave

+0

ループに新しい属性を追加しないでください。 –

答えて

1

あなたは100万マイル離れていません。既存の名前空間宣言属性をすべて削除してから、必要な属性をルートに追加するだけです。残りは世話をする。

var doc = XDocument.Load(@"C:\Temp\Source.xml"); 

doc.Descendants().Attributes().Where(x => x.IsNamespaceDeclaration).Remove(); 
doc.Root.Add(new XAttribute(XNamespace.Xmlns + "root", "urn:root:v1")); 
doc.Root.Add(new XAttribute(XNamespace.Xmlns + "loc", "urn:location:v2")); 

doc.Save(@"C:\Temp\Target.xml"); 

デモはthis fiddleを参照してください。

+0

2番目の名前空間がどのように機能するかは面白いです。 ''は以前にすべてを削除したので、 'loc'名前空間接頭辞を使うべきですか?私のXSLTは* CountryName *ノードを明示的に対象としていました。 +1とにかく! – Parfait

+1

@Parfait *宣言*が削除されても、モデルは依然として 'CountryName'の* namespace *を知っています。 [書くとき](http://referencesource.microsoft.com/#System.Xml.Linq/System/Xml/Linq/XLinq.cs,da605610f51d6a49)、['GetPrefixOfNamespace'](https://msdn.microsoft .com/en-us/library/system.xml.linq.xelement。getprefixofnamespace(v = vs.110).aspx)を使用してスコープ内のプレフィックスを調べ、見つかった場合はそのプレフィックスを使用します。 –

0

XSLTは、XMLファイルを変換するための特別な言語です。私は個人的にC#を知らないのですが、XSLT 1.0スクリプトを実行できることはわかります。回答hereを参照してください。また、使用するXSLTプロセッサでは、このソリューションにはdocument()関数を許可する必要があります。

XSLT(としての.xslファイルを保存し、通知の名前空間は、ヘッダ内で宣言)

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
           xmlns:root="urn:root:v1" xmlns:local="urn:location:v2"> 
    <xsl:output omit-xml-declaration="no" indent="yes"/> 
    <xsl:strip-space elements="*"/> 

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

    <xsl:template match="*"> 
     <xsl:element name="root:{name()}" namespace="urn:root:v1"> 
     <xsl:copy-of select="document('')/*/namespace::local"/> 
     <xsl:apply-templates select="node()|@*"/> 
     </xsl:element> 
    </xsl:template>  

    <xsl:template match="*[local-name()='CountryName']"> 
     <xsl:element name="local:{name()}" namespace="urn:location:v2"> 
     <xsl:apply-templates select="node()|@*"/> 
     </xsl:element> 
    </xsl:template> 

</xsl:stylesheet> 

C#(上記のリンクを参照)

var myXslTrans = new XslCompiledTransform(); 

myXslTrans.Load("XSLTScript.xsl"); 
myXslTrans.Transform("Input.xml", "Output.xml"); 

XML出力

<?xml version="1.0"?> 
<root:Main xmlns:root="urn:root:v1" xmlns:local="urn:location:v2" version="1.0"> 
    <root:Report> 
    <root:Title>Some Value</root:Title> 
    </root:Report> 
    <root:Content> 
    <root:Address> 
     <local:CountryName>Australia</local:CountryName> 
    </root:Address> 
    </root:Content> 
</root:Main> 
関連する問題