我正在努力将Filemaker XML文件转换为更加用户友好的东西。默认情况下,FM会将一个段落中的每个句子存储在一个元素中,我希望将所有这些句子分组。
下面的XML显示了它的原始形式:
<Para>
<ParaLine>
<String>This is just some spacefiller, so some text to </String>
</ParaLine>
<ParaLine>
<String>show how things look now. Go to </String>
<XRef>
<XRefName value="Heading"/>
</XRef>
<String>“</String>
<String>More info here</String>
<String>” </String>
</ParaLine>
<ParaLine>
<String>(page</String>
<Char value="HardSpace" type="enum"/>
<String>27)</String>
<XRefEnd/>
<String>to get more details.</String>
</ParaLine>
</Para>
我的目标是双重的,首先我想得到任何[para]分组中的所有字符串值。使用以下xlst:
相对容易实现<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" xmlns="http://www.w3.org/1999/xhtml" encoding="UTF-8" indent="yes"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="text()">
<xsl:value-of select="normalize-space(.)"/>
</xsl:template>
<xsl:template match="/">
<xsl:result-document href="test.xml">
<xsl:apply-templates/>
</xsl:result-document>
</xsl:template>
<xsl:template match="String">
<xsl:choose>
<xsl:when test="preceding-sibling::*[1][name()='String']">
<xsl:text> </xsl:text>
<xsl:value-of select="text()"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="text()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="ParaLine">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="Char[@value='HardSpace']">
<xsl:text> </xsl:text>
</xsl:template>
</xsl:stylesheet>
所以我目前的输出如下:
<Para>This is just some spacefiller, so some text to show how things look now. Go to
<XRef><XRefName value="Heading"/></XRef>
“ More info here ” (page 27)
<XRefEnd/>to get more details.
</Para>
然而,我的第二个目标是在单个标签中获取[XRef]和[XRefEnd]之间的内容,我可以使用一些额外的转换来做到这一点,但我想知道是否可以在一次旅行中。我最终的“梦想”是在一次旅行中降低XML输出:
<Para>
<local xml:lang="en">This is just some spacefiller, so some text to show how things look now. Go to
<XRef XRefName="Heading">“ More info here ” (page 27)</XRef>
to get more details.</local>
有关如何使用有限数量的转换执行此操作的任何提示?
提前致谢!
答案 0 :(得分:0)
以下是一个例子:
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0">
<xsl:output indent="yes"/>
<xsl:template match="Para">
<xsl:copy>
<xsl:for-each-group select="ParaLine/*" group-starting-with="XRef">
<xsl:choose>
<xsl:when test="self::XRef">
<xsl:variable name="name" select="XRefName/@value"/>
<xsl:for-each-group select="current-group() except ." group-ending-with="XRefEnd">
<xsl:choose>
<xsl:when test="position() eq 1">
<XRef XRefName="{$name}">
<xsl:apply-templates select="current-group()[position() ne last()]"/>
</XRef>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-group()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-group()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
当我在发布的输入上使用Saxon 9.3和上面的样式表时,我得到以下结果:
<?xml version="1.0" encoding="UTF-8"?>
<Para>This is just some spacefiller, so some text to show how things look now. Go to <XRef XRefName="Heading">“More info here” (page27)</XRef>to get more details.</Para>