重组节点

时间:2012-05-18 17:19:30

标签: xslt xslt-2.0

我想匹配节点属性值,如果相同的值出现在另一个节点属性中,我必须合并它们。所以例如我有一个xml

<xml>
   <title>
   <metadata>
    <ref cite="ABC" relevance="2"/>
    </metadata>
     <body>
       <para>
            <text>(some text from title)</text>
      </para>
     </body>
    </title>
    <title>
      <metadata>
         <ref cite="ABC" relevance="1"/>
      </metadata>
     <body>
       <para>
            <text>(some more text from title 2)</text>
      </para>
     </body>
    </title>

    <mainbody>
        <targetref cite="ABC"/>
        <text>This is a text</text>  
   </mainbody>
 </xml>

所以在转换之后输出应该如下所示,所以基于引用元素title / metadata / ref的“ABC”并按相关性排序(1,2 ....),标题的内容将合并到文本中元素“targetref”的引用符合元素“ref”的引用

的主体元素
<xml>
  <mainbody>
    <targetref cite="ABC"/>
    <text>This is a text 
        <para><text>(some more text from title 2)</text></para>
       <para><text>(some text from title)</text></para> 
    </text>
   </mainbody>
 </xml> 

由于

2 个答案:

答案 0 :(得分:0)

这里有一些符合你想要的xslt:

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

<xsl:output omit-xml-declaration="no" method="xml"/>
<xsl:strip-space elements="*"/>

<xsl:template match="mainbody">
<xsl:copy>
        <xsl:copy-of select="targetref"/>
        <xsl:element name="text">
            <xsl:value-of select="."/>
            <xsl:variable name="key" select="targetref/@cite"/>
            <xsl:for-each select="/xml/title[metadata/ref/@cite=$key]">
                <xsl:sort data-type="number" select="metadata/ref/@relevance" order="ascending" />
                <xsl:copy-of select="body/para"/>
            </xsl:for-each>
        </xsl:element>
    </xsl:copy>
</xsl:template>

<xsl:template match="xml/title"/>

<xsl:template match="xml">
    <xsl:copy>
        <xsl:apply-templates/>
    </xsl:copy>
</xsl:template>

<xsl:template match="*">
    <xsl:apply-templates/>
</xsl:template>

</xsl:stylesheet>

技巧是在正常流程上忽略节点xml / title,我们关注mainbody标签,之后我们调用for-each来选择和排序所需的节点,并将信息写入我们想要的主体内部。选择需要一个变量($ key)来过滤主体上的指定

答案 1 :(得分:0)

执行此操作的一种方法是使用密钥根据元数据参考值查找标题记录:

<xsl:key name="ref" match="title" use="metadata/ref/@cite" />

然后,假设您位于主体内的 text 元素上,您可以像这样查找它们,并同时对它们进行排序

<xsl:apply-templates select="key('ref', preceding-sibling::targetref/@cite)/body/para">
   <xsl:sort select="../../metadata/ref/@relevance" />

这是完整的XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:key name="ref" match="title" use="metadata/ref/@cite" />
   <xsl:template match="title" />

  <xsl:template match="mainbody/text">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
      <xsl:apply-templates select="key('ref', preceding-sibling::targetref/@cite)/body/para" >
         <xsl:sort select="../../metadata/ref/@relevance" />
      </xsl:apply-templates>
    </xsl:copy>
  </xsl:template>

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

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

<xml>
    <mainbody>
        <targetref cite="ABC"/>
        <text>This is a text
            <para>
                <text>(some more text from title 2)</text>
            </para>
            <para>
                <text>(some text from title)</text>
            </para></text>
    </mainbody>
</xml>