2017-02-20 42 views
1

我尝试使用XSLT将Doxygen XML转换为文本输出。 Doxygen的返回此XML结构:XSLT:选择没有子树的所有元素

<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> 

我尽量只选择不包含simplesect节点或任何其他“复杂的树状结构”是para节点。
我试试这个XPath:

detaileddescription/para/node() 

但是这也将返回simplesect/para节点。
那么,如何才能选择仅包含text()节点和formula节点作为兄弟节点的para节点?

+1

要选择不包含'simplesect'的'para',可以使用'/ detaileddescription/para [not(simplesect)]'。我不确定你的意思是“*其他任何”复杂的树形结构“*” –

+0

你真的想要选择什么'para'节点/元素? – zx485

回答

0

的XPath来仅获取ulink节点将是

//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> 
+0

感谢帮助了很多,我使用的匹配表达式: '第[计数(后裔:: *)> 0和计数(文本())> 0]' ,因为我想获得该节点 '带有<公式编号=“6”>的长文本$ \ LaTeX $代码' 因此,我总是需要一个文本节点,如果存在公式节点。 – Phil

+1

@Phil请在问题中显示完整的XSLT样式表,以及您期望的文本输出。谢谢。 –

1

表达detaileddescription/para/node()不选择simplesect/para节点。它选择simplesect元素,但不选择其子元素。我觉得你的困惑是关于发生了什么你选择了一个节点。您没有向我们展示您如何处理选定的节点,但是例如,如果您将xsl:copy-of指令应用于选定的节点,则该指令不仅会复制选定的节点,还会复制其所有子节点和子节点。

如果您希望某个节点出现在输出中,而其子节点也不会出现,那么选择该节点还不够,您需要对其进行转换(具体来说,创建排除其子节点的节点副本)。

0

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

然后做你写道:

  • 写模板匹配para
  • 阅读(直接)子文本节点,但只包含“真实”文本 (非空文本)。
  • 然后检查你是否真的有东西。
  • 如果是(您的para包含一些非空文本(忘记 “深层”位于文本节点)),请执行标识转换。
  • 否则您的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>