使用xslt设置xml节点顺序

时间:2012-03-11 19:37:40

标签: xml xslt sorting

我正在使用xml来表示带有块和单词的句子。问题是在xml我给出的单词是根据其父块设置顺序,而不是在句子中的顺序。这就是xml的样子:

<SENTENCE>
  <CHUNK ord="4">
    <CHUNK ord="2">
      <CHUNK ord="1">
        <WORD ord="0" />
      </CHUNK>
      <WORD ord="2" />
      <CHUNK ord="3">
        <WORD ord="0" />>
      </CHUNK>
    </CHUNK>
    <WORD ord="1" />
      <WORD ord="0" />
    <CHUNK ord="5">
      <WORD ord="0">
        <WORD ord="1" />
      </WORD>
      <CHUNK ord="6">
        <WORD ord="0">
          <WORD ord="2">
            <WORD ord="3" />
            <WORD ord="1" />
            </WORD>
        </WORD>
      </CHUNK>
    </CHUNK>
    <CHUNK ord="7">
      <WORD ord="0">
        <WORD ord="1" />
      </WORD>
    </CHUNK>
    <CHUNK ord="8">
      <WORD ord="0" />
    </CHUNK>
  </CHUNK>
</SENTENCE>

我需要知道单词在句子中的实际顺序,以进行其他处理,但不会丢失xml的结构。例如,在上面给出的示例中,输出xml应如下所示:

<SENTENCE>
  <CHUNK ord="4">
    <CHUNK ord="2">
      <CHUNK ord="1">
        <WORD ord="0" senOrd="0" />
      </CHUNK>
      <WORD ord="2" senOrd="1" />
      <CHUNK ord="3">
        <WORD ord="0" senOrd="3" />>
      </CHUNK>
    </CHUNK>
    <WORD ord="1" senOrd="4" />
    <WORD ord="0" senOrd="5" />
    <CHUNK ord="7">
      <WORD ord="0" senOrd="12">
        <WORD ord="1" senOrd="13" />
      </WORD>
    </CHUNK>
    <CHUNK ord="8">
      <WORD ord="0" senOrd="14" />
    </CHUNK>
  </CHUNK>
  <CHUNK ord="5">
    <WORD ord="0" senOrd="6">
      <WORD ord="1" senOrd="7" />
    </WORD>
    <CHUNK ord="6">
      <WORD ord="0" senOrd="8">
        <WORD ord="2" senOrd="10">
          <WORD ord="3" senOrd="11" />
          <WORD ord="1" senOrd="9" />
        </WORD>
      </WORD>
    </CHUNK>
  </CHUNK>
</SENTENCE>

我一直试图通过使用xslt在每个单词元素中创建一个新属性,这将在句子中显示它的顺序,但我甚至不知道从哪里开始。如果有人能帮助我,我会很感激。

这是一个可能的xml给出英文句子“这只是一个xml的例子”:

<SENTENCE>
<CHUNK ord="1">
    <CHUNK ord="0">
        <WORD ord="1" form="is">
            <WORD ord="0" form="this" />
        </WORD>
    </CHUNK>
    <WORD ord="1" form="just">
    <CHUNK ord="2">
        <WORD ord="2" form="of">
            <WORD ord="0" form="an" />
        </WORD>
        <WORD ord="1" form="example" />
        <CHUNK ord="0">
            <WORD ord="1" form="xml" />
            <WORD ord="0" form="the" />
        </CHUNK>
    </CHUNK>
    </CHUNK>
</CHUNK>

senOrd属性指示的是每个单词在句子中的顺序。

2 个答案:

答案 0 :(得分:0)

我不确定您的问题描述是否存在,但这会产生请求的输出

<xsl:stylesheet  version="1.0"
         xmlns:xsl="http://www.w3.org/1999/XSL/Transform">


<xsl:template match="*|@*">
 <xsl:copy>
  <xsl:apply-templates select="@*"/>
  <xsl:apply-templates/>
 </xsl:copy>
</xsl:template>

<xsl:template match="word/@ord">
 <xsl:copy-of select="."/>
 <xsl:attribute name="senOrd">
  <xsl:value-of select=". + ancestor::chunk[1]/@ord"/>
 </xsl:attribute>
</xsl:template>

</xsl:stylesheet>

答案 1 :(得分:0)

我认为您需要将属于 chunk 元素的所有单词元素本身用较低的顺序计算,加上所有单词元素在同一个块中降低 ord 属性。

<xsl:value-of select="count(//WORD[ancestor::CHUNK[1]/@ord &lt; $currentOrd])
   + count(//WORD[ancestor::CHUNK[1]/@ord = $currentOrd][@ord &lt; current()/@ord])"/>

currentOrd 定义如下:

<xsl:variable name="currentOrd" select="ancestor::CHUNK[1]/@ord"/>

因此,给出以下XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="xml" indent="yes"/>

   <xsl:template match="WORD">
      <xsl:variable name="currentOrd" select="ancestor::CHUNK[1]/@ord"/>
      <xsl:copy>
         <xsl:apply-templates select="@*"/>
         <xsl:attribute name="senOrd">
            <xsl:value-of select="count(//WORD[ancestor::CHUNK[1]/@ord &lt; $currentOrd]) + count(//WORD[ancestor::CHUNK[1]/@ord = $currentOrd][@ord &lt; current()/@ord])"/>
         </xsl:attribute>
         <xsl:apply-templates/>
      </xsl:copy>
   </xsl:template>

   <xsl:template match="*|@*">
      <xsl:copy>
         <xsl:apply-templates select="@*"/>
         <xsl:apply-templates/>
      </xsl:copy>
   </xsl:template>
</xsl:stylesheet>

当应用于您的示例XML时,输出以下内容

<SENTENCE>
   <CHUNK ord="4">
      <CHUNK ord="2">
         <CHUNK ord="1">
            <WORD ord="0" senOrd="0"/>
         </CHUNK>
         <WORD ord="2" senOrd="1"/>
         <CHUNK ord="3">
            <WORD ord="0" senOrd="2"/>
         </CHUNK>
      </CHUNK>
      <WORD ord="1" senOrd="4"/>
      <WORD ord="0" senOrd="3"/>
      <CHUNK ord="5">
         <WORD ord="0" senOrd="5">
            <WORD ord="1" senOrd="6"/>
         </WORD>
         <CHUNK ord="6">
            <WORD ord="0" senOrd="7">
               <WORD ord="2" senOrd="9">
                  <WORD ord="3" senOrd="10"/>
                  <WORD ord="1" senOrd="8"/>
               </WORD>
            </WORD>
         </CHUNK>
      </CHUNK>
      <CHUNK ord="7">
         <WORD ord="0" senOrd="11">
            <WORD ord="1" senOrd="12"/>
         </WORD>
      </CHUNK>
      <CHUNK ord="8">
         <WORD ord="0" senOrd="13"/>
      </CHUNK>
   </CHUNK>
</SENTENCE>