XSLT:选择没有子树的所有元素

时间:2017-02-20 22:41:27

标签: xml xslt xpath

我尝试使用XSLT将Doxygen XML转换为文本输出。 Doxygen返回此XML结构:

<detaileddescription>
    <para>a long text with <formula id="6">$ \LaTeX $</formula> code</para>
    <para>
        <simplesect kind="see">
            <para>
                <ulink url="url">url description</ulink>
            </para>
        </simplesect>
    </para>    
</detaileddescription>

我尝试仅选择不包含para节点的simplesect节点或任何其他&#34;复杂树结构&#34;。
我试试这个XPath:

detaileddescription/para/node()

但这也将返回simplesect/para节点 那么,我怎样才能只选择既不包含para节点也不包含text()节点的formula节点作为兄弟节点?

3 个答案:

答案 0 :(得分:1)

表达式detaileddescription/para/node()未选择simplesect/para节点。它选择simplesect元素,但不选择其子元素。我认为您的混淆是关于选择节点后发生的事情。您还没有向我们展示您对所选节点的处理方式,但是如果您将xsl:copy-of指令应用于所选节点,则不仅会复制所选节点,还会复制其所有子节点和后代节点

如果您希望节点出现在输出中而不显示其子节点,那么它不足以选择节点,您需要对其进行转换(具体而言,创建排除其节点的节点的副本)儿童)。

答案 1 :(得分:0)

仅获取ulink节点的XPath将是

//para[count(descendant::*) &lt; 2 and  count(text()) = 0]

实现这一目标的完整XSLT-1.0是

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

  <xsl:template match="text()" />

  <xsl:template match="//para[count(descendant::*) &lt; 2 and  count(text()) = 0]">
    <xsl:copy-of select="." />
  </xsl:template>

</xsl:stylesheet>

哪个输出

<?xml version="1.0"?>
<para>
    <ulink url="url">url description</ulink>
</para>

答案 2 :(得分:0)

您编写的 para节点不包含......任何...复杂的树结构

然后按照你写的那样做:

  • 撰写与para匹配的模板。
  • 读取(直接)子文本节点,但仅包含&#34; real&#34;文本 (不是空的)。
  • 然后检查你是否真的有东西。
  • 如果是(您的para包含一些非空文本(忘记了) &#34;更深&#34;找到文本节点)),执行身份转换。
  • 否则您的para将无法呈现。

下面你有一个完整的解决方案。我添加了strip-space以避免空输出行。

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

  <xsl:template match="para">
    <xsl:variable name="txt" select="text()[normalize-space()]"/>
    <xsl:if test="$txt">
      <xsl:copy><xsl:apply-templates select="@*|node()"/></xsl:copy>
    </xsl:if>
  </xsl:template>

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