1

我有一个 xml 文档:

<xml>
   <staff>
       <seq_no num="0">0</seq_no>
       <name>xyz</name>
   </staff>
   <staff>
       <seq_no num="1">1</seq_no>
       <name>xyz</name>
   </staff>
   <staff>
      <seq_no num="1">2</seq_no>
      <name>abc</name>
   </staff>
   <staff>
      <seq_no num="3">3</seq_no>
      <name>abc</name>
   </staff>
 </xml>

如果任何 seq_no 相同,我想将数字添加到 seq_no/@num。如果没有重复,则不会添加任何内容。

上面的输出应该是:

    <xml>
     <staff>  
          <seq_no num="[1]1">0</seq_no>
          <name>xyz</name>
       </staff>
     <staff>
          <seq_no num="[2]1">1</seq_no>
          <name>xyz</name>
     </staff>
     <staff>
         <seq_no num="[3]1">2</seq_no>
         <name>abc</name>
      </staff>
     <staff>
         <seq_no num="[4]3">3</seq_no>
         <name>abc</name>
      </staff>
</xml>

将 [1],[2],[3],[4] 分别添加到 seq_no/@num。我开始使用这样的匹配模板

<xsl:template match="seq_no/num">
<seq_no>
  <xsl:attribute name="num">
    <xsl:text>[</xsl:text><xsl:number select="." format="1" level="any"  /><xsl:text>]</xsl:text>
    <xsl:value-of select="@num"></xsl:value-of>
  </xsl:attribute>
<xsl:value-of select="."></xsl:value-of>
</seq_no>
</xsl:template>

但是在控制位置以及如何检查其他 seq_no 的重复 num 时遇到麻烦...

输入没有任何重复的数字:

 <xml>
   <staff>
       <seq_no num="0">0</seq_no>
       <name>xyz</name>
   </staff>
   <staff>
       <seq_no num="1">1</seq_no>
       <name>xyz</name>
   </staff>
   <staff>
      <seq_no num="2">2</seq_no>
      <name>abc</name>
   </staff>
   <staff>
      <seq_no num="3">3</seq_no>
      <name>abc</name>
   </staff>
 </xml>.

输出应与输入相同,无需处理。

 <xml>
   <staff>
       <seq_no num="0">0</seq_no>
       <name>xyz</name>
   </staff>
   <staff>
       <seq_no num="1">1</seq_no>
       <name>xyz</name>
   </staff>
   <staff>
      <seq_no num="1">2</seq_no>
      <name>abc</name>
   </staff>
   <staff>
      <seq_no num="3">3</seq_no>
      <name>abc</name>
   </staff>
 </xml>
4

2 回答 2

1

逻辑似乎仍然与您的输入/输出示例不匹配,但这就是我认为您正在尝试做的事情......

XML 输入

<xml>
    <staff>
        <seq_no num="0">0</seq_no>
        <name>xyz</name>
    </staff>
    <staff>
        <seq_no num="1">1</seq_no>
        <name>xyz</name>
    </staff>
    <staff>
        <seq_no num="1">2</seq_no>
        <name>abc</name>
    </staff>
    <staff>
        <seq_no num="3">3</seq_no>
        <name>abc</name>
    </staff>
</xml>

XSLT 1.0

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

    <!--Check for any duplicates in the doc.-->
    <xsl:variable name="vDups" select="boolean(//seq_no[@num=preceding::seq_no/@num])"/>

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

    <xsl:template match="seq_no">
        <xsl:copy>
            <xsl:choose>
                <xsl:when test="$vDups">
                    <xsl:attribute name="num">
                        <xsl:text>[</xsl:text>
                        <xsl:number level="any"/>
                        <xsl:text>]</xsl:text>
                        <xsl:value-of select="."/>                      
                    </xsl:attribute>
                    <xsl:apply-templates select="@*[not(name()='num')]|node()"/>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:apply-templates select="@*|node()"/>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

XML 输出

<xml>
   <staff>
      <seq_no num="[1]0">0</seq_no>
      <name>xyz</name>
   </staff>
   <staff>
      <seq_no num="[2]1">1</seq_no>
      <name>xyz</name>
   </staff>
   <staff>
      <seq_no num="[3]2">2</seq_no>
      <name>abc</name>
   </staff>
   <staff>
      <seq_no num="[4]3">3</seq_no>
      <name>abc</name>
   </staff>
</xml>

可选的、更简洁的 XSLT 2.0 模板替换:

<xsl:template match="seq_no[$vDups]">
    <xsl:copy>
        <xsl:attribute name="num">
            <xsl:text>[</xsl:text>
            <xsl:number level="any"/>
            <xsl:text>]</xsl:text>
            <xsl:value-of select="."/>                      
        </xsl:attribute>
        <xsl:apply-templates select="@*[not(name()='num')]|node()"/>
    </xsl:copy>
</xsl:template>
于 2012-08-29T03:55:33.170 回答
1

这种转变

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

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

 <xsl:template match="seq_no[/*/*/seq_no[@num = following::seq_no/@num]]">
  <seq_no num="[{count(preceding::seq_no)+1}]{.}">
   <xsl:apply-templates/>
  </seq_no>
 </xsl:template>
</xsl:stylesheet>

应用于提供的 XML 文档时

<xml>
    <staff>
        <seq_no num="0">0</seq_no>
        <name>xyz</name>
    </staff>
    <staff>
        <seq_no num="1">1</seq_no>
        <name>xyz</name>
    </staff>
    <staff>
        <seq_no num="1">2</seq_no>
        <name>abc</name>
    </staff>
    <staff>
        <seq_no num="3">3</seq_no>
        <name>abc</name>
    </staff>
</xml>

产生想要的正确结果

<xml>
   <staff>
      <seq_no num="[1]0">0</seq_no>
      <name>xyz</name>
   </staff>
   <staff>
      <seq_no num="[2]1">1</seq_no>
      <name>xyz</name>
   </staff>
   <staff>
      <seq_no num="[3]2">2</seq_no>
      <name>abc</name>
   </staff>
   <staff>
      <seq_no num="[4]3">3</seq_no>
      <name>abc</name>
   </staff>
</xml>

当对这个 XML 文档应用相同的转换(如上)时(没有@num重复):

<xml>
    <staff>
        <seq_no num="0">0</seq_no>
        <name>xyz</name>
    </staff>
    <staff>
        <seq_no num="1">1</seq_no>
        <name>xyz</name>
    </staff>
    <staff>
        <seq_no num="2">2</seq_no>
        <name>abc</name>
    </staff>
    <staff>
        <seq_no num="3">3</seq_no>
        <name>abc</name>
    </staff>
</xml>

再次产生所需的正确结果:

<xml>
  <staff>
    <seq_no num="0">0</seq_no>
    <name>xyz</name>
  </staff>
  <staff>
    <seq_no num="1">1</seq_no>
    <name>xyz</name>
  </staff>
  <staff>
    <seq_no num="2">2</seq_no>
    <name>abc</name>
  </staff>
  <staff>
    <seq_no num="3">3</seq_no>
    <name>abc</name>
  </staff>
</xml>
于 2012-08-29T13:02:20.767 回答