1

这是我的输入

<someAccounts>
    <Account>
           <type>ABC</type>
           <number>123456789</number>               
           <productCode>011</productCode>
           <packageCode>022</packageCode>
        </Account>
       <Account>
           <type>BBC</type>
           <number>234567890</number>               
           <productCode>011</productCode>
           <packageCode>022</packageCode>
        </Account>
       <Account>
           <type>CBC</type>
           <number>345678900</number>               
           <productCode>011</productCode>
           <packageCode>022</packageCode>
        </Account>
        <Account>
           <type>DBC</type>
           <number>999999999</number>               
           <productCode>011</productCode>
           <packageCode>022</packageCode>
        </Account>
       <Account>
           <type>FBC</type>
           <number>999999999</number>               
           <productCode>011</productCode>
           <packageCode>022</packageCode>
        </Account>
  </someAccounts>

其中有 2 个帐户对象具有相同的编号。我想消除两个具有相同编号的帐户对象(不仅仅是一个)。基本上这应该是我的输出

<someAccounts>
 <Account>
           <type>ABC</type>
           <number>123456789</number>               
           <productCode>011</productCode>
           <packageCode>022</packageCode>
        </Account>
       <Account>
           <type>BBC</type>
           <number>234567890</number>               
           <productCode>011</productCode>
           <packageCode>022</packageCode>
        </Account>
       <Account>
           <type>CBC</type>
           <number>345678900</number>               
           <productCode>011</productCode>
           <packageCode>022</packageCode>
        </Account>
  </someAccounts>

我试过用这个

        <xsl:for-each>
          <xsl:copy-of select="someAccounts/Account[number != current()/number]"/>
        </xsl:for-each>

这只会消除重复的一个,但我需要删除两个帐户,我该如何实现这一点。请帮忙


如何在不附加子节点值的情况下获取 xml 节点的值?

如何在不附加子节点值的情况下获取 xml 节点的值?Innertext 给出了附加子项的值。有什么方法可以从父节点的值中删除该字符串?/text() 不起作用,因为我正在反序列化 xml 文件。

4

3 回答 3

2

首先,您可能会在XSLT 身份转换的基础上进行复制,以跨 XML 中的现有元素进行复制

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

这意味着您只需要编写一个模板来忽略具有重复数字元素的Account元素。如果您想检查具有重复数字元素的Account元素,那么您可以定义一个键来查找它们

<xsl:key name="account" match="Account" use="number" />

有了这个,你只需要这个简单的模板来忽略重复

<xsl:template match="Account[key('account', number)[2]]" />    

即,如果至少有两个具有相同编号的Account元素,则忽略Account元素。

试试这个 XSLT

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

   <!-- Key to look up Account elements by their number -->
   <xsl:key name="account" match="Account" use="number" />

   <!-- Ignore Account elements for which there are at least two with the same number -->
   <xsl:template match="Account[key('account', number)[2]]" />    

    <!-- Copy all other elements as-is -->
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>
于 2013-11-12T22:05:12.837 回答
0

这是另一个更简单的解决方案,基于这样的假设,即如果number元素的值已经出现在任何之前 Account,那么它Account不会被复制。基本上,这是使用这个附加模板的身份转换:

<xsl:template match="Account[./number=preceding-sibling::*/number]"/>

在上面,我们匹配任何Account元素,它的数字也出现在前面的兄弟中。如果是这样,什么也不做。其他所有内容都被复制。

这是完整的代码:

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

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

    <xsl:template match="Account[./number=preceding-sibling::*/number]"/>

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

</xsl:stylesheet>

当应用于 OP 中的输入 XMl 时,它给出:

<someAccounts>
    <Account>
        <type>ABC</type>
        <number>123456789</number>
        <productCode>011</productCode>
        <packageCode>022</packageCode>
    </Account>
    <Account>
        <type>BBC</type>
        <number>234567890</number>
        <productCode>011</productCode>
        <packageCode>022</packageCode>
    </Account>
    <Account>
        <type>CBC</type>
        <number>345678900</number>
        <productCode>011</productCode>
        <packageCode>022</packageCode>
    </Account>
    <Account>
        <type>DBC</type>
        <number>999999999</number>
        <productCode>011</productCode>
        <packageCode>022</packageCode>
    </Account>
</someAccounts>
于 2013-11-13T03:54:58.870 回答
0

以下 XSLT 1.0 产生所需的输出。它使用显式for-eachif构造。该键有助于找到由相等数字定义的帐户集。仅复制大小为 1 的组。

<?xml version="1.0" encoding="UTF-8"?>
<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" />

  <!-- create key to find the accounts given by a number -->
  <xsl:key name="number_key" match="Account" use="number/text()"/>

  <xsl:template match="/someAccounts">

    <xsl:copy>

      <xsl:for-each select="Account">

        <!-- key('number_key', ./number) returns a set of accounts with a given number -->
        <!-- the next if only copies if the this set has size = 1 -->

        <xsl:if test="count(key('number_key', ./number)) = 1">
          <xsl:copy-of select="."/>
        </xsl:if>

      </xsl:for-each>

    </xsl:copy>

  </xsl:template>

</xsl:stylesheet>

在 XSLT 2.0 中,该for-each-group构造可用于确定组大小。该方法的结构保持不变:

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

  <xsl:template match="/someAccounts">

    <xsl:copy>

      <xsl:for-each-group select="Account" group-by="number">

        <!-- current-group() returns a set of accounts with a given number -->
        <!-- the next if only copies if the this set has size = 1 -->

        <xsl:if test="count(current-group()) = 1">
          <xsl:copy-of select="current-group()[1]"/>
        </xsl:if>

      </xsl:for-each-group>

    </xsl:copy>

  </xsl:template>

</xsl:stylesheet>
于 2013-11-12T22:25:08.150 回答