使用XSLT删除CDATA值为空的元素。

huangapple go评论92阅读模式
英文:

Remove element with XSLT where CDATA value is empty

问题

我对XSLT相当陌生,发现很难正确理解它...

我想要实现的是,将XML中每个CDATA没有值的<text>元素删除。

我的XML如下:

  1. <description>
  2. <internet>
  3. <texts_short>
  4. <text locale="de"><![CDATA[]]></text>
  5. <text locale="en"><![CDATA[EXF/RETAIL]]></text>
  6. </texts_short>
  7. <texts_long>
  8. <text locale="de"><![CDATA[]]></text>
  9. </texts_long>
  10. </internet>
  11. <vehicle>
  12. <texts_short/>
  13. <texts_long>
  14. <text locale="en"><![CDATA[Backend Functions Bundle]]></text>
  15. </texts_long>
  16. <texts_text2speech>
  17. <text locale="de"><![CDATA[]]></text>
  18. </texts_text2speech>
  19. </vehicle>
  20. </description>

我已经准备好了以下的XSLT,它会删除没有条件的每个text元素:

  1. <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  2. <xsl:output method="xml" indent="yes"/>
  3. <xsl:strip-space elements="*"/>
  4. <xsl:template match="@*|node()">
  5. <xsl:copy>
  6. <xsl:apply-templates select="@*|node()"/>
  7. </xsl:copy>
  8. </xsl:template>
  9. <xsl:template match="text"/>
  10. </xsl:stylesheet>

要实现只删除CDATA值为空的<text>元素,可以修改XSLT如下:

  1. <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  2. <xsl:output method="xml" indent="yes"/>
  3. <xsl:strip-space elements="*"/>
  4. <xsl:template match="@*|node()">
  5. <xsl:copy>
  6. <xsl:apply-templates select="@*|node()"/>
  7. </xsl:copy>
  8. </xsl:template>
  9. <xsl:template match="text">
  10. <xsl:if test="string-length(normalize-space(.//text())) > 0">
  11. <xsl:copy>
  12. <xsl:apply-templates select="@*|node()"/>
  13. </xsl:copy>
  14. </xsl:if>
  15. </xsl:template>
  16. </xsl:stylesheet>

这个XSLT将只保留具有非空CDATA值的<text>元素,其他的将被删除。

英文:

I am quite new to XSLT and find it very hard to understand properly..

I want to achieve that every <text> element where my CDATA has no value should be removed from the XML.

My XML looks like this:

  1. &lt;description&gt;
  2. &lt;internet&gt;
  3. &lt;texts_short&gt;
  4. &lt;text locale=&quot;de&quot;&gt;&lt;![CDATA[]]&gt;&lt;/text&gt;
  5. &lt;text locale=&quot;en&quot;&gt;&lt;![CDATA[EXF/RETAIL]]&gt;&lt;/text&gt;
  6. &lt;texts_long&gt;
  7. &lt;text locale=&quot;de&quot;&gt;&lt;![CDATA[]]&gt;&lt;/text&gt;
  8. &lt;/texts_long&gt;
  9. &lt;/internet&gt;
  10. &lt;vehicle&gt;
  11. &lt;texts_short/&gt;
  12. &lt;texts_long&gt;
  13. &lt;text locale=&quot;en&quot;&gt;&lt;![CDATA[Backend Functions Bundle]]&gt;&lt;/text&gt;
  14. &lt;/texts_long&gt;
  15. &lt;texts_text2speech&gt;
  16. &lt;text locale=&quot;de&quot;&gt;&lt;![CDATA[]]&gt;&lt;/text&gt;
  17. &lt;/texts_text2speech&gt;
  18. &lt;/vehicle&gt;
  19. &lt;/description&gt;

I have already prepared the following XSLT which removes every text element with no condition:

  1. &lt;xsl:stylesheet version=&quot;1.0&quot; xmlns:xsl=&quot;http://www.w3.org/1999/XSL/Transform&quot;&gt;
  2. &lt;xsl:output method=&quot;xml&quot; indent=&quot;yes&quot;/&gt;
  3. &lt;xsl:strip-space elements=&quot;*&quot;/&gt;
  4. &lt;xsl:template match=&quot;@*|node()&quot;&gt;
  5. &lt;xsl:copy&gt;
  6. &lt;xsl:apply-templates select=&quot;@*|node()&quot;/&gt;
  7. &lt;/xsl:copy&gt;
  8. &lt;/xsl:template&gt;
  9. &lt;xsl:template match=&quot;text&quot;/&gt;
  10. &lt;/xsl:stylesheet&gt;

How can I achieve that only the <text> elements with empty CDATA value will be removed - so that only the one with text "EXF/RETAIL" and "Backend Functions Bundle" will stay?

Thank you in advance!

答案1

得分: 1

你可以使用&lt;xsl:template match=&quot;text[not(normalize-space())]&quot;/&gt;,但这将移除没有内容、空的CDATA部分、只包含空格的CDATA部分等的text元素。在XSLT中无法知道元素的内容是由CDATA部分还是普通文本节点在词法标记中提供的。

英文:

What you can do is use &lt;xsl:template match=&quot;text[not(normalize-space())]&quot;/&gt; but that will remove text elements having no content, an empty CDATA section, a CDATA section with only white space etc. There is no way in XSLT to know whether the element's content was provided in the lexical markup by a CDATA section or an ordinary text node.

答案2

得分: 0

翻译后的代码部分如下:

  1. <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  2. <xsl:output method="xml" indent="yes" cdata-section-elements="text"/>
  3. <xsl:strip-space elements="*"/>
  4. <xsl:template match="@*|node()">
  5. <xsl:copy>
  6. <xsl:apply-templates select="@*|node()"/>
  7. </xsl:copy>
  8. </xsl:template>
  9. <xsl:template match="text[not(normalize-space())]"/>
  10. </xsl:stylesheet>
英文:

It looks like adding cdata-section-elements="text" to the output together with Martin Honnen's answer solved my problem:

  1. &lt;xsl:stylesheet version=&quot;1.0&quot; xmlns:xsl=&quot;http://www.w3.org/1999/XSL/Transform&quot;&gt;
  2. &lt;xsl:output method=&quot;xml&quot; indent=&quot;yes&quot; cdata-section-elements=&quot;text&quot;/&gt;
  3. &lt;xsl:strip-space elements=&quot;*&quot;/&gt;
  4. &lt;xsl:template match=&quot;@*|node()&quot;&gt;
  5. &lt;xsl:copy&gt;
  6. &lt;xsl:apply-templates select=&quot;@*|node()&quot;/&gt;
  7. &lt;/xsl:copy&gt;
  8. &lt;/xsl:template&gt;
  9. &lt;xsl:template match=&quot;text[not(normalize-space())]&quot;/&gt;
  10. &lt;/xsl:stylesheet&gt;

huangapple
  • 本文由 发表于 2023年2月6日 17:39:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/75359578.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定