我有一个带有以下结构的xml文档。我正在编写一个转换,我想从节点B输出文本,但忽略元素C和文本节点“title”。基本上我想提取文本“text goes here”并将其输出到一个新元素中,并将所有空格规范化。有人可以帮忙吗?以下是我到目前为止所尝试的内容。
Input Doc
<A>
<B>
<C>title</C>
text goes here
</B>
</A>
Required output doc
<d>text goes here</d>
Solution A:
<xsl:template match="B">
<d>
<xsl:copy-of select="./text()"/>
</d>
</xsl:template>
问题:元素之间的空白被保留,所以我得到这样的东西:
<d>
Text goes here
</d>
我还尝试在解决方案A的模板中使用值语句(<xsl:value-of select="./text()"/>
),但这根本不会返回任何文本。声明有问题吗?
我应该提一下,我使用以下内容覆盖了默认文本处理模板:<xsl:template match="text()" />
由于
答案 0 :(得分:5)
<xsl:value-of select="./text()"/>
返回“无”的原因是./text()
将返回由当前节点的所有直接子文本节点组成的节点 set 。 value-of
节点集是其第一个项的字符串值,在本例中是开头<B>
和开头{{1}之间的仅空白文本节点标签。这同样适用于次最明显的<C>
,因为它再次将节点集转换为字符串(第一个节点值),然后规范化该字符串中的空间。相反,您需要单独规范化每个子文本节点:
normalize-space(text())
有一点需要注意的是,如果你有像
这样的输入<d>
<xsl:for-each select="text()">
<xsl:value-of select="normalize-space(.)"/>
</xsl:for-each>
</d>
然后你会得到
的输出<A>
<B>
<C>title</C>
text goes here
<C>subtitle</C>
more text here
</B>
</A>
字幕两边的位之间没有空格。如果这是一个问题,你可以使用像
这样的技巧<d>text goes heremore text here</d>
仅迭代那些包含非空白字符的文本节点子节点,并在除第一节之外的所有节点之前添加空格。
<d>
<xsl:for-each select="text()[normalize-space(.)]">
<xsl:if test="position() > 1"><xsl:text> </xsl:text></xsl:if>
<xsl:value-of select="normalize-space(.)"/>
</xsl:for-each>
</d>
答案 1 :(得分:0)
我最接近的是选择the child
axis://B/child::text()
。
child
轴只返回当前上下文节点的直接子节点的文本节点,因此它与title
节点不匹配。
答案 2 :(得分:0)
试试这段代码!
我没有使用<copy-of>
,而是使用了模板覆盖!
我用D代替B ..
我从输出中删除<C>
。这解决了问题的一半,因此<C>
节点的文本没有出现在输出中。
我将规范化空间函数应用于所有文本节点..因此将删除额外的空格:)
这是代码:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="B">
<d>
<xsl:apply-templates select="node()"/>
</d>
</xsl:template>
<xsl:template match="C"/>
<xsl:template match="text()">
<xsl:value-of select="normalize-space(.)"/>
</xsl:template>
</xsl:stylesheet>