2017-06-21 1 views
0

セルフクロージングノードとXMLでペア空のノードを置き換えますように(私はすべての空のノード開閉ペアを交換したいと思います私はこのようになりその一部がいくつかのXML、持って

<BasicInfo> 
    <Foo>80</Foo> 
    <Bar> 
    </Bar> 
</BasicInfo> 

<Bar>上記の)単一自己終了ノードと、このような何か与える:

<BasicInfo> 
    <Foo>80</Foo> 
    <Bar /> 
</BasicInfo> 

私はXMLで、2が等価であることを知っているのとXSLTは、それがそうで出力空のノードに望んでいるとどのように選択しますが、ということ私は多くの空のノードと2つの予想されるファイルサイズの違いがあります解釈は心配する価値があるほど十分です。私はxmlを可能な限り効率的に保存したいと思います。 「XSI:nilを」

上記のSQL Serverからの作成されたXMLは、すべて削除され、別のXSLTで変換後のSQL値とのxmlns宣言Server 2008には、取り残さ:それはこのスタイルシートです

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" version="1.0"> 
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" omit-xml-declaration="yes" /> 
    <xsl:strip-space elements="*" /> 
    <xsl:template match="*"> 
    <xsl:element name="{local-name(.)}"> 
     <xsl:apply-templates select="@* | node()" /> 
    </xsl:element> 
    </xsl:template> 
    <xsl:template match="@*"> 
    <xsl:attribute name="{local-name(.)}"> 
     <xsl:value-of select="." /> 
    </xsl:attribute> 
    </xsl:template> 
    <xsl:template match="@*[local-name(.)='noNamespaceSchemaLocation']" /> 
    <xsl:template xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" match="@xsi:nil" /> 
</xsl:stylesheet> 

こと後ろに開いていると閉じてペアを残して - それは自己閉鎖ノードの後ろに残すように強制する任意の方法は、または独自の新しい効果を生成するために新しいxsltを作ることですか?悲しいことに、ノードを削除

はオプションではありません。

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" version="1.0"> 
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" omit-xml-declaration="yes" /> 
    <xsl:strip-space elements="*" /> 
    <!--Remove all the empty nodes--> 
    <!--copy nodes--> 
    <xsl:template match="node()|@*"> 
    <xsl:copy> 
     <xsl:apply-templates select="node()|@*" /> 
    </xsl:copy> 
    </xsl:template> 
    <!--match only those with no contents at all--> 
    <xsl:template match="*[not(@*|*|comment()|processing-instruction()) and normalize-space()='']" /> 
    <!--now check all those that have existing but empty children and don't return the children if they are empty--> 
    <xsl:template match="*"> 
    <xsl:copy> 
     <xsl:if test="descendant::text()"> 
     <xsl:apply-templates select="node()" /> 
     </xsl:if> 
    </xsl:copy> 
    </xsl:template> 
</xsl:stylesheet> 

しかし、これは私が持っている最も近いです。私はこの質問をしている他の人を見つけましたが、xsltの知識が乏しいということは、私のニーズに応じたソリューションを変更するのに問題があることを意味します(上記のものを整理するのは非常に時間がかかりました!それは、正規化 - 空間の線に沿った何かが行く方法だと思われますか?私は本当にいくつかの助けに感謝します!

NB。 xmlはSQL Server 2008 R2によって生成され、FOR XML PATHを使用し、XSLTスクリプトはサーバーのxml列に格納されます。オペランドタイプXSLTを持つSSIS 2008のXMLタスクが変換を適用します。

+0

があなたのコントロール下にこのXMLを作成しますか? – Shnugo

+0

はい、SQL Serverを使用していることに注意してください。 –

+0

''それを行う必要があります。 'XSLCompiledTransform'を使用して変換を実行していますか?スタイルシートで定義した出力設定を使用するには、 'XmlWriter'に対して' XSLCompiledTransform.OutputSettings'を 'XmlWriter.Create'に渡す必要があります。 –

答えて

1

考える:

XML

<BasicInfo> 
    <Foo>80</Foo> 
    <Bar> 
    </Bar> 
</BasicInfo> 

次のスタイルシート:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> 
<xsl:strip-space elements="*"/> 

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

</xsl:stylesheet> 

をしますリターン:

<?xml version="1.0" encoding="UTF-8"?> 
<BasicInfo> 
    <Foo>80</Foo> 
    <Bar/> 
</BasicInfo> 

説明:

<xsl:strip-space elements="*"/>命令はBar要素に含まれる空白だけのテキスト・ノード、およびプロセッサを除去する自己として自動的に出力空の要素終了タグ。

+0

私は ''ビットを追加したときにこれと同じようにスクリプトを試しましたが、うまくいきませんでした。回答)。 –

+0

結果が異なる場合は、入力が異なるか、プロセッサの動作が異なります。ほとんどの場合でも、プロセッサは自己終了タグを使用する義務はありません。もしあなたがそうしなければ、それを強制する方法はありません - 少なくともスタイルシートを通してではありません。 –

+0

hmm。それは残念です。XSLT変換を適用する別の方法を使用する場合、ビルトインXMLタスクの代わりにSSISのスクリプトタスクを使用するなど、プロセッサや動作を変更するものを選択することはできますか?あなたの意見では、これは実験的な価値があると思いますか? –

1

NULLでの通常の動作は、要素を完全に排除することです。

ELEMENTS XSINILを入力すると、NULLの場合でもすべての要素がエンジンに入力されます。

ハックトリックは、ここのような属性を削除することがあります

CREATE TABLE #Demo (Id INT IDENTITY(1,1) NOT NULL 
        ,Value1 VARCHAR(30) NOT NULL 
        ,Value2 VARCHAR(30) NULL); 
INSERT #Demo(Value1,Value2) 
    VALUES('Bar',NULL); 


WITH XMLNAMESPACES ('http://tempuri.org/MySchema.xsd' AS xsd) 
SELECT This.Id 
    ,(SELECT T.Value1 
       ,T.Value2 
     FROM #Demo T 
     WHERE T.Id = This.Id 
     FOR XML PATH('BasicInfo'),ELEMENTS XSINIL,TYPE) AS TheXml 
INTO #Demo2 
FROM #Demo AS This; 
UPDATE #Demo2 SET TheXml.modify('delete (//*/@*[local-name()="nil"])'); 

SELECT * FROM #Demo2 
GO 
DROP TABLE #Demo 
DROP TABLE #Demo2; 
+0

それは確かにSQLで正しい出力を提供します - 私は明日にそれを与えます。 XSLTにカプセル化されていないのは残念ですが、ハックトリックはトリックよりも優れています! –

+0

SQL Serverでの変更を使用すると、正しい解決方法が提供されますが、後でスタイルシートを使用すると、すべて復元されます。私はこれを使用し、物事のまわりで自分の道を尽くそうとします。このように異なる行動をとるべきではないことが残念です。 –

+0

@HighPlainsGrifter主な質問は:これはなぜ重要なのですか?あなたが質問したところでは、保存場所を節約したいと思っています。少なくともSQL-ServerではXML **は表示されている文字列**には格納されませんが、階層ツリーとして格納されます。違いはありません。*通常の振る舞いは、 'NULL '値の要素を除外することです(より少ないバイト!)。どの要素が予想されるかを消費者に伝えるスキーマを追加するだけです。だからもう一度:なぜか? – Shnugo

関連する問題