2016-07-20 13 views
0

xsltを使用して特定のXMLを変換しようとしています。注意は、特定の子ノードが存在しない場合、親ノードを削除する必要があるということです。私はいくつかのテンプレートマッチングをしましたが、私は立ち往生しています。どんな助けもありがとう。子ノードが空の場合に親ノードを削除します。

入力XML:

<?xml version="1.0" encoding="UTF-8"?> 
<main> 
    <item> 
     <value> 
      <item> 
       <value>ABC</value> 
       <key>test1</key> 
      </item> 
      <item> 
       <value>XYZ</value> 
       <key>test2</key> 
      </item> 
       <item> 
       <value></value> 
       <key>test3</key> 
      </item> 
     </value> 
    </item> 
    <item> 
     <value /> 
     <key>test4</key> 
    </item> 
    <item> 
     <value>PQR</value> 
     <key>test5</key> 
    </item> 
</main> 

予想される出力:

<?xml version="1.0" encoding="UTF-8"?> 
<main> 
    <item> 
     <value> 
      <item> 
       <value>ABC</value> 
       <key>test1</key> 
      </item> 
      <item> 
       <value>XYZ</value> 
       <key>test2</key> 
      </item> 
     </value> 
    </item> 
    <item> 
     <value>PQR</value> 
     <key>test5</key> 
    </item> 
</main> 

私は、例えばテンプレートマッチングを使用した場合に問題があります

<xsl:template match="item[not(value)]"/>deleting the parent node if child node is not present in xml using xsltに記載されているとおり、main/item/valueも空であるため、すべてを完全に削除します。

私が必要とするのは、要素が空の場合は削除ですが、要素に子要素がない場合にのみ行います。

+0

さらに、キーtest1とtest2の値が空の場合、トップレベルの項目要素も出力から除外する必要があります。 – Ady211

答えて

1

あなたが最初にあなたが必要とするすべては、すべての子孫item要素にマッチするテンプレートである、そして、XSLTのアイデンティティーテンプレートで

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

を開始する必要がありますリーフvalueの要素は空です。

<xsl:template match="item[not(descendant::value[not(*)][normalize-space()])]" /> 

テンプレートは一致しますが、出力しません。

私はこれを正しく読めば、あなたがやりたい

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
    <xsl:output method="xml" indent="yes" /> 

    <xsl:template match="item[not(descendant::value[not(*)][normalize-space()])]" /> 

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

これは魅力のように機能します。このxsltは、項目/値に対してmain/item/value(空で子ノード項目を持つ)をどのように区別しますか?そのトリックをやっていないのですか? – Ady211

+0

はい。 'not(*)'を実行すると、子要素がないかどうかがチェックされるため、 "leaf"要素にのみ一致します。 –

0

私はあなたがその要素を削除したいと思います。それらの子が要素かテキストノードかどうかはまったくありません。このテンプレートを挿入してみてください。

<xsl:template match="item"> 
 
    <xsl:if test="exists(value/node())"> 
 
     <xsl:copy> 
 
      <xsl:copy-of select="@*"/> 
 
      <xsl:apply-templates/> 
 
     </xsl:copy> 
 
    </xsl:if> 
 
</xsl:template>

+0

私はそれが動作していないとxsltコンパイルエラーを与えてみました。エラー:XSLTProcessor :: transformToXml():xmlXPathCompiledEval:1つのオブジェクトがスタックに残っています。 – Ady211

+0

@ Ady211あなたの質問のタグが示すように、XSLT 2.0を使用していますか? –

+0

私はxslt 1.0を使用しています。 – Ady211

0

このXSLTを試してみてください:

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:template match="item[not(value[node()])]"/> 

</xsl:stylesheet> 

これは持っていない任意のitemを削除しますvalue子供と一部内容。

関連する問題