Reputation: 129
I try to transform Doxygen XML into a text output with XSLT. Doxygen returns this XML structure:
<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>
I try to select only that para
node that does not contain the simplesect
node or any other "complex tree structure".
I try this XPath:
detaileddescription/para/node()
but this will also return the simplesect/para
node.
So, how can I select only the para
node that does neither contain a text()
node nor a formula
node as a sibling?
Upvotes: 1
Views: 444
Reputation: 30971
You wrote para node that does not contain ... any ... complex tree structure.
Then do as you wrote:
para
.para
contains some not empty text (forgetting about
"deeper" located text nodes)), execute an identity transform.para
will not be rendered.Below you have a complete solution. I added strip-space
to avoid empty output rows.
<?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>
Upvotes: 0
Reputation: 163302
The expression detaileddescription/para/node()
does not select the simplesect/para
node. It selects the simplesect
element, but does not select its children. I think your confusion is about what happens after you select a node. You haven't shown us what you do with the selected nodes, but if for example you apply the xsl:copy-of
instruction to the selected nodes, that will copy not only the selected nodes but all their children and descendants as well.
If you want a node to appear in the output without its children also appearing, then it's not enough to select the node, you need to transform it (specifically, to create a copy of the node that excludes its children).
Upvotes: 1
Reputation: 29022
An XPath to get only the ulink
node would be
//para[count(descendant::*) < 2 and count(text()) = 0]
A full XSLT-1.0 to achieve this is
<?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::*) < 2 and count(text()) = 0]">
<xsl:copy-of select="." />
</xsl:template>
</xsl:stylesheet>
which output is
<?xml version="1.0"?>
<para>
<ulink url="url">url description</ulink>
</para>
Upvotes: 0