组合2个给定元素名称之间的内容

时间:2011-09-15 15:33:16

标签: xslt-2.0

我正在努力将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>

有关如何使用有限数量的转换执行此操作的任何提示?

提前致谢!

1 个答案:

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