我需要将以下xml输出到浏览器,如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<content>
<text>
<h1>Services</h1>
<h2>Engineering</h2>
This is the first bit of text:
<listofitems>
<listitem>Database Analysis Tools</listitem>
<listitem>Website Development</listitem>
<listitem>Intranet Development</listitem>
<listitem>Database Development</listitem>
</listofitems>
This is the second piece of text:
<listofitems>
<listitem>Hardware</listitem>
<listitem>Software</listitem>
</listofitems>
This is the final piece of text.
</text>
</content>
问题在于<文本>元素-未包含在其自己的标记中的位,即"This is the first bit of text:"、"This are the second piece of text:"one_answers"This是最后一段文本。">
如果我使用<xsl:value-of-select="."/>,但很明显,它们在原始XML中并不是这样出现的。如果我使用<xsl:value-of-select="text()"/>我一无所获(我相信text()只引用了第一个子节点,在本例中它是另一个元素)。
我可以用<xsl:value-of-select="node()[last()]/self::text()">;我可以通过直接引用每个text()节点来访问它,例如<xsl:value-of-select="text()[3]"/>,但由于这意味着要与任何格式的随机XML一起使用,我将无法以这种方式直接引用节点。我在text()[*]上尝试了for each,但没有成功。你知道我该怎么做吗?
如果文本节点是text
元素的子元素,则编写一个单独的模板来匹配它们:
<xsl:template match="text()[parent::text]">
这样,介于两者之间的任何其他子元素都不会干扰。然后,编写第二个模板来防止XSLT处理器也在listitem
元素内部输出文本:
<xsl:template match="*[parent::text]"/>
如果您省略了上面的模板匹配,XSLT的默认行为将导致作为listitem
的子级的任何文本节点也被输出。
请注意,XSLT1.0和2.0在处理文本节点方面有所不同。您的方法之一:
<xsl:value-of select="text()"/>
实际上输出XSLT2.0中的所有文本节点。下面是一个适用于1.0和2.0的样式表。
样式表
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:strip-space elements="*"/>
<xsl:template match="//text">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="text()[parent::text]">
<xsl:value-of select="."/>
</xsl:template>
<xsl:template match="*[parent::text]"/>
</xsl:stylesheet>
输出
This is the first bit of text: This is the second piece of text: This is the final piece of text.
或者,如果不需要处理text
的子元素,请将select
属性添加到apply-templates
:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="//text">
<xsl:apply-templates select="text()"/>
</xsl:template>
<xsl:template match="text()[parent::text]">
<xsl:copy/>
</xsl:template>
</xsl:stylesheet>
当这个样式表:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:strip-space elements="*"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="content/text/text()">
<span><xsl:value-of select="."/></span>
</xsl:template>
</xsl:stylesheet>
应用于您的输入。它输出:
<?xml version="1.0" encoding="utf-8"?>
<content>
<text>
<h1>Services</h1>
<h2>Engineering</h2>
<span>This is the first bit of text:</span>
<listofitems>
<listitem>Database Analysis Tools</listitem>
<listitem>Website Development</listitem>
<listitem>Intranet Development</listitem>
<listitem>Database Development</listitem>
</listofitems>
<span>This is the second piece of text:</span>
<listofitems>
<listitem>Hardware</listitem>
<listitem>Software</listitem>
</listofitems>
<span>This is the final piece of text.</span>
</text>
</content>
这能解决你的问题吗?
经过多次摆弄,我认为这已经足够接近了,可以接受:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="*">
<xsl:param name="indent"/>
<xsl:if test="parent::* or preceding-sibling::*">
<br/>
</xsl:if>
<xsl:value-of select="$indent" disable-output-escaping="yes"/>
<!-- open angle brackets -->
<<xsl:value-of select="name()"/>
<!-- output any attributes and values -->
<xsl:for-each select="@*">
<xsl:text disable-output-escaping="yes">&nbsp;</xsl:text>
<xsl:value-of select="name(.)"/>="<b><xsl:value-of select="."/></b>"
</xsl:for-each>
<!-- close angle brackets -->
>
<!-- output text content -->
<xsl:apply-templates>
<xsl:with-param name="indent"><xsl:value-of select="$indent"/>&nbsp;&nbsp;&nbsp;&nbsp;</xsl:with-param>
</xsl:apply-templates>
<!-- close tag -->
<xsl:if test="child::*">
<br/><xsl:value-of select="$indent" disable-output-escaping="yes"/>
</xsl:if>
</<xsl:value-of select="name()"/>>
</xsl:template>
<xsl:template match="text()">
<xsl:value-of select="."/>
</xsl:template>
</xsl:stylesheet>
这就给出了:
<content>
<text>
<h1>Services</h1>
<h2>Engineering</h2> This is the first bit of text:
<listofitems>
<listitem>Database Analysis Tools</listitem>
<listitem>Website Development</listitem>
<listitem>Intranet Development</listitem>
<listitem>Database Development</listitem>
</listofitems> This is the second piece of text:
<listofitems>
<listitem>Hardware</listitem>
<listitem>Software</listitem>
</listofitems> This is the final piece of text.
</text>
</content>
这些烦人的文本片段至少在大致正确的区域,模板应该可以与任何旧的XML一起使用
非常感谢你的帮助。