【问题标题】:XML empty nodes, XSLT return closed tagsXML 空节点,XSLT 返回封闭标签
【发布时间】:2015-09-28 00:03:51
【问题描述】:

当其中任何一个为空时,我的 xslt 会返回封闭标签(类别和描述标签)。在下面的示例中,Title 将返回封闭的描述标签,而 Title2 将返回封闭的类别标签。

我正在将我的源代码输入到应用程序中,因为有没有打开的封闭标签,所以我没有得到预期的结果。

这是我的输入:

    <?xml version="1.0" encoding="utf-8"?>
    <rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
    <title>Title</title>
    <description>Description</description>
    <link>https://url/</link>
    <language>en-us</language>
    <lastBuildDate>Sun, 27 Sep 2015 21:07:40 GMT</lastBuildDate>

    <image>
    <title>Title</title>
    <width>144</width><height>400</height>
    <link>https://url</link>
    <url>https://url</url>
    </image>

    <item>
    <title>Title</title>
    <link>https://html</link>
    <guid isPermaLink="true">https://html</guid>
    <comments>https://html</comments>
    <pubDate>Thu, 24 Sep 2015 16:01:42 GMT</pubDate>
    <description><![CDATA[]]></description>
    <category>headline,government,usa,spyware</category>
    </item>

    <item>
    <title>Title2</title>
    <link>https://txt</link>
    <guid isPermaLink="true">https://txt</guid>
    <comments>https://html</comments>
    <pubDate>Fri, 25 Sep 2015 06:54:51 GMT</pubDate>
    <description>DescritpionExist</description>
    <category></category>
    </item>

    </channel>
    </rss>

以下是我的 XSLT:

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <!--skips new lines and indents in-->    
    <xsl:output method="xml" indent="yes"/> 
    <!--if,error-->
    <xsl:strip-space elements="*"/>
    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>

    <!--skips completely-->
    <xsl:template match="channel/title"/>
    <xsl:template match="channel/description"/>
    <xsl:template match="channel/link"/>
    <xsl:template match="channel/language"/>
    <xsl:template match="channel/lastBuildDate"/>
    <xsl:template match="image"/>
    <xsl:template match="item/link"/>

    <!--skips node if empty-->
    <xsl:template match="item/title[not(child::node())]"/>
    <xsl:template match="item/link[not(child::node())]"/>
    <xsl:template match="item/guid[not(child::node())]"/>
    <xsl:template match="item/comments[not(child::node())]"/>


    <!--delimits values if seperated by comma-->
    <xsl:template match="item/category[contains(.,',')]">  
        <xsl:variable name="elementName" select="name(..)"/>

        <xsl:call-template name="splitIntoElements">
            <xsl:with-param name="baseName" select="name(..)" />
            <xsl:with-param name="txt" select="." />    
        </xsl:call-template>

    </xsl:template>

    <xsl:template name="splitIntoElements">
        <xsl:param name="baseName" />
        <xsl:param name="txt" />
        <xsl:param name="delimiter" select="','" />
        <xsl:param name="index" select="1" />

        <xsl:variable name="first" select="substring-before($txt, $delimiter)" />
        <xsl:variable name="remaining" select="substring-after($txt, $delimiter)" />

        <xsl:element name="{$baseName}-{$index}">
            <xsl:choose>
                <xsl:when test="$first">
                    <xsl:value-of select="$first" />
                </xsl:when>
                <xsl:otherwise>
                    <xsl:value-of select="$txt" />
                </xsl:otherwise>
            </xsl:choose>
        </xsl:element>     
        <xsl:if test="$remaining">
            <xsl:call-template name="splitIntoElements">
                <xsl:with-param name="baseName" select="$baseName" />
                <xsl:with-param name="txt" select="$remaining" />
                <xsl:with-param name="index" select="$index+1" />
                <xsl:with-param name="delimiter" select="$delimiter" />
            </xsl:call-template>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>

跳过或删除空字段没有帮助:

<xsl:template match="item/category[not(child::node())]"/>
<xsl:template match="item/description[not(child::node())]"/>

这也没有帮助

<xsl:template match="*[normalize-space() = '']" />

我什至尝试用尽 if then 子句在结束标签之前添加一个开始标签,但我无法得到结果。

我的输出是:

<item>
             <title>Title</title>
             <guid isPermaLink="true">http</guid>
             <comments>http</comments>
             <pubDate>Thu, 24 Sep 2015 01:54:35 GMT</pubDate>
             <description/>
             <item-1>headline</item-1>
             <item-2>government</item-2>
             <item-3>privacy</item-3>
             <item-4>usa</item-4>
          </item>
          <item>
             <title>Title2</title>
             <guid isPermaLink="true">http</guid>
             <comments>comment</comments>
             <pubDate>Sat, 26 Sep 2015 03:14:57 GMT</pubDate>
             <description>Description</description>
             <category/>
          </item>

预期的输出应该是:

<item>
         <title>Title</title>
         <guid isPermaLink="true">http</guid>
         <comments>http</comments>
         <pubDate>Thu, 24 Sep 2015 01:54:35 GMT</pubDate>
         <description><description/>
         <item-1>headline</item-1>
         <item-2>government</item-2>
         <item-3>privacy</item-3>
         <item-4>usa</item-4>
      </item>
      <item>
         <title>Title2</title>
         <guid isPermaLink="true">http</guid>
         <comments>comment</comments>
         <pubDate>Sat, 26 Sep 2015 03:14:57 GMT</pubDate>
         <description>Description</description>
         <category><category/>
      </item>

【问题讨论】:

  • 这是您输入的错字吗:Title/title>?
  • 是的,绝对是错字,感谢指出,这是我第一次在这里发帖,在尝试解决我的 xml 问题后已经筋疲力尽了。

标签: xml xslt tags normalization tokenize


【解决方案1】:

解决您在上述 cmets 中的 XML 中遇到的问题(您的结束标题标签已损坏)我从您的输入中得到了这个:

<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
<channel>
  <item>
     <title>Title</title>
     <guid isPermaLink="true">https://html</guid>
     <comments>https://html</comments>
     <pubDate>Thu, 24 Sep 2015 16:01:42 GMT</pubDate>
     <description/>
     <item-1>headline</item-1>
     <item-2>government</item-2>
     <item-3>usa</item-3>
     <item-4>spyware</item-4>
  </item>
  <item>
     <title>Title2</title>
     <guid isPermaLink="true">https://txt</guid>
     <comments>https://html</comments>
     <pubDate>Fri, 25 Sep 2015 06:54:51 GMT</pubDate>
     <description>DescritpionExist</description>
     <category/>
  </item>
</channel>
</rss>

我看不出任何符合标准的 XSLT 处理器将如何接受您的输入(它是损坏的 XML)或使用

传递该结果

【讨论】:

  • 嗨@kevin-brown,感谢您的意见。但是,我无法完全理解您的评论。你能更具体一点吗? XML源是packetstorm rss feed,我无法控制源文件,而氧气开发人员能够提供输出,但节点为空时带有结束标签。
【解决方案2】:

&lt;xsl:output method="html" /&gt; 将解决封闭标签的问题。但是,是否有任何解决方案可以在不切换到 html 输出的情况下解决此问题?

【讨论】:

  • 没有。这里没有什么可以“修复”的。在 XML 中,&lt;category/&gt;&lt;category&gt;&lt;/category&gt; 完全相同。如果您的目标应用程序不理解&lt;category/&gt;,那么它就无法理解 XML。
  • @IKavanagh 不,实际上这问题的正确答案。
  • @michael.hor257k 是答案中的问题引起了我的注意。
  • @IKavanagh 是的,如果存在更好的答案,那么这是一个答案,然后是一个问题。它没有,所以它真的更像是一个沉思而不是一个问题。
  • 我正在使用的应用程序不接受 html 输出方法,因此寻找替代答案。
猜你喜欢
  • 1970-01-01
  • 2013-06-11
  • 2022-01-23
  • 1970-01-01
  • 2012-06-09
  • 1970-01-01
  • 2018-07-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多