在XML中创建引用

时间:2014-01-05 15:15:58

标签: xml xslt

我有一个代表文章的XML文件。我正在使用客户端xslt将其转换为html进行显示。

我试图在整个xml文件中嵌入引用,其中许多引用重复。我想知道我是否可以将引用从xml文件的内容部分中分离出来然后将它们链接在一起,这样我就不会重复多次了。

我认为我可以将ID和IDREF作为属性添加到<p><reference>标记中(使用XML Schema作为名称空间将在以后很重要)。因此:

<article>
  <body>
    <content>
      <p>This is the first paragraph.</p>
      <reference>Patrick</reference>
    <content>
    </content>
      <p>This is the second paragraph and a lovely one it is too.</p>
      <reference>Donald</reference>
    <content>
    </content>
      <p>This paragraph uses the same reference as paragraph 1.</p>
      <reference>Patrick</reference>
    </content>
  </body>
</article>

......会变成......

<article>
  <body>
    <p IDREF="ref1">This is the first paragraph.</p>
    <p IDREF="ref2">This is the second paragraph and a lovely one it is too.</p>
    <p IDREF="ref1">This paragraph uses the same reference as paragraph 1.</p>
  </body>
  <references>
    <reference ID="#ref1">Patrick</reference>
    <reference ID="#ref2">Donald</reference>
  </references>
</article>

到目前为止,我失败了。我是在正确的轨道上吗?

2 个答案:

答案 0 :(得分:1)

我会编写像

这样的模板
<xsl:template match="body">
  <xsl:copy>
    <xsl:apply-templates select="content/p"/>
  </xsl:copy>
  <references>
    <xsl:apply-templates select="content/reference"/>
  </references>
</xsl:template>

<xsl:template match="p">
  <p id="{generate-id()}">
    <xsl:apply-templates/>
  </p>
</xsl:template>

<xsl:template match="reference">
  <reference idref="#{generate-id(preceding-sibling::p[1])}">
    <xsl:apply-templates/>
  </reference>
</xsl:template>

或者,如果需要,您可以使用模式两次处理p元素。如果需要,那么当然不是使用generate-id,而是使用xsl:numbercount生成自己的ID。

答案 1 :(得分:1)

我认为你想要这样的东西(没有彻底测试过):

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:key name="kRef" match="reference" use="." />

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

<xsl:template match="/article" >
<xsl:copy>
    <xsl:apply-templates/>
    <references>
        <xsl:apply-templates select="//reference[count(. | key('kRef', .)[1]) = 1]" mode="index"/>
    </references>
</xsl:copy>
</xsl:template>

<xsl:template match="p">
<xsl:variable name="myRef" select="following-sibling::reference[1]" />
<xsl:copy>
    <xsl:attribute name="IDREF">
        <xsl:value-of select="count(key('kRef', $myRef)[1]/preceding::reference)+1" />  
    </xsl:attribute>
    <xsl:apply-templates/>
</xsl:copy>
</xsl:template>

<xsl:template match="reference"/>

<xsl:template match="reference" mode="index">
<xsl:copy>
    <xsl:attribute name="ID">
        <xsl:value-of select="count(preceding::reference)+1" />
    </xsl:attribute>
    <xsl:value-of select="."/>
</xsl:copy>
</xsl:template>

</xsl:stylesheet>

结果,使用您的样本输入:

<?xml version="1.0" encoding="utf-8"?>
<article>
  <body>
    <content>
      <p IDREF="1">This is the first paragraph.</p>
      <content/>
      <p IDREF="2">This is the second paragraph and a lovely one it is too.</p>
      <content/>
      <p IDREF="1">This paragraph uses the same reference as paragraph 1.</p>
    </content>
  </body>
  <references>
    <reference ID="1">Patrick</reference>
    <reference ID="2">Donald</reference>
  </references>
</article>

以上是上述的修改版本,使用自动生成的ID来索引引用,而不是计算以前的出现次数:

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:key name="kRef" match="reference" use="." />

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

<xsl:template match="/article" >
<xsl:copy>
    <xsl:apply-templates/>
    <references>
        <xsl:apply-templates select="//reference[count(. | key('kRef', .)[1]) = 1]" mode="index"/>
    </references>
</xsl:copy>
</xsl:template>

<xsl:template match="p">
<xsl:variable name="myRef" select="following-sibling::reference[1]" />
<xsl:copy>
    <xsl:attribute name="IDREF">
        <xsl:value-of select="generate-id(key('kRef', $myRef)[1])" />   
    </xsl:attribute>
    <xsl:apply-templates/>
</xsl:copy>
</xsl:template>

<xsl:template match="reference"/>

<xsl:template match="reference" mode="index">
<xsl:copy>
    <xsl:attribute name="ID">
        <xsl:value-of select="generate-id(.)" />
    </xsl:attribute>
    <xsl:value-of select="."/>
</xsl:copy>
</xsl:template>

</xsl:stylesheet>

这里的结果看起来像(取决于处理器):

<?xml version="1.0" encoding="utf-8"?>
<article>
  <body>
    <content>
      <p IDREF="idm758912">This is the first paragraph.</p>
      <content/>
      <p IDREF="idm251232">This is the second paragraph and a lovely one it is too.</p>
      <content/>
      <p IDREF="idm758912">This paragraph uses the same reference as paragraph 1.</p>
    </content>
  </body>
  <references>
    <reference ID="idm758912">Patrick</reference>
    <reference ID="idm251232">Donald</reference>
  </references>
</article>