使用Bash根据特定属性查找重复的XML数据

时间:2018-07-09 12:56:54

标签: xml bash duplicates

是否有可能根据特定的XML属性提取所有Xml值: 例如,我需要使用所有具有相同auth_username的手机(第一个和最后一个手机具有相同的auth_username

    <Fund>
    <mobile>
    <auth_username>736994</auth_username>
    <client_name>736994_iPad</client_name>
    <first_name>Yamelin</first_name>
    <last_name>test</last_name>
    </mobile>
    <mobile>
    <auth_username>735139</auth_username>
    <client_name>735139_iPad</client_name>
    <first_name>Eunbi</first_name>
    <last_name>Eunbi</last_name>
    </mobile>
    <mobile>
    <auth_username>733279</auth_username>
    <client_name>733279_iPad</client_name>
    <first_name>wang</first_name>
    <last_name>test</last_name>
    </mobile>
    <mobile>
    <auth_username>737618</auth_username>
    <client_name>737618_iPad</client_name>
    <first_name>test</first_name>
    <last_name>testLast</last_name>
    </mobile>
    <mobile>
    <auth_username>736994</auth_username>
    <client_name>734131_iPad</client_name>
    <first_name>Kai</first_name>
    <last_name>test</last_name>
    </mobile>
    </Fund>

所需的输出必须类似于:

    <Fund>
    <mobile>
    <auth_username>736994</auth_username>
    <client_name>736994_iPad</client_name>
    <first_name>Yamelin</first_name>
    <last_name>test</last_name>
    </mobile>
    <mobile>
    <auth_username>736994</auth_username>
    <client_name>734131_iPad</client_name>
    <first_name>Kai</first_name>
    <last_name>test</last_name>
    </mobile>
    </Fund>

我尝试了xmlstarlet,但是我只将auth_username作为输出

DataFund = $(xmlstarlet sel -T -t -m“ Fund / mobile” -n -v“ auth_username”〜/ Desktop / DeviceAndUserFund2.csv | sort | uniq -d)

这是另一种方式吗?

1 个答案:

答案 0 :(得分:1)

Bash功能本身并不十分适合您的XML要求类型。但是,这里有两个都使用XSLT stylesheet的解决方案。

解决方案1-使用 xmlstarlet

  1. 首先保存以下.xsl。我们将文件命名为get-dupes.xsl

    get-dupes.xsl

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
      <xsl:output method="xml" omit-xml-declaration="no" indent="yes"/>
      <xsl:strip-space elements="*"/>
    
      <xsl:key name="duplicates" match="mobile" use="auth_username"/>
    
      <xsl:template match="/Fund">
        <xsl:element name="{name(/*)}">
          <xsl:copy-of select="mobile[count(key('duplicates', auth_username)) > 1]"/>
        </xsl:element>
      </xsl:template>
    
    </xsl:stylesheet>
    
  2. 然后通过您的CLI运行以下 xmlstarlet 命令:

    xml tr /path/to/get-dupes.xsl /path/to/input.xml
    

    请注意,上面命令中的/path/to/部分应更改为实际文件的真实路径。

  3. 生成的xml将包含所有具有相同<mobile>..</mobile>值的<auth_username>元素。

更多说明:

  • 如果要省略xml声明(即<?xml version="1.0"?>,则可以在命令中添加--omit-decl选项。例如:

    xml tr --omit-decl /path/to/get-dupes.xsl /path/to/input.xml
    
  • 如果需要,您的源xml数据也可以通过管道传递到xml tr命令。例如:

    cat /path/to/input.xml | xml tr /path/to/get-dupes.xsl
    
  • 要将结果XML分配给名为DataFund的变量,可以执行以下操作:

    DataFund="$(xml tr /path/to/get-dupes.xsl /path/to/input.xml)"
    
  • 要将结果XML保存到新文件,可以按照以下示例使用重定向(>):

    xml tr /path/to/get-dupes.xsl /path/to/input.xml > path/to/output.xml
    
  • 有关xml tr命令和可用选项的更多信息,请参见here

    xml tr命令的一般用法是:

      

    xml tr [<options>] <xsl-file> {-p|-s <name>=<value>} [ <xml-file-or-uri> ... ]


解决方案2-使用 xsltproc

您还可以使用xsltproc(已预先安装在macOS上)实现这一目标。

使用名为get_dupes.xsl的XSLT样式表(如上所示),您可以:

  1. 通过运行以下命令从文件读取源XML:

    xsltproc /path/to/get-dupes.xsl /path/to/input.xml
    
  2. 或者,将源XML传递给xsltproc。例如:

    cat input.xml | xsltproc /path/to/get-dupes.xsl -
    

    请注意,以上使用了连字符(-)从标准输入中读取源xml数据。

  3. 或者,将结果XML分配给名为DataFund的变量,您可以执行以下操作:

    DataFund="$(xsltproc /path/to/get-dupes.xsl /path/to/input.xml)"
    
  4. xsltproc 没有可省略xml声明的选项。为此,您需要将 get-dupes.xsl 中的omit-xml-declaration="no"属性更改为omit-xml-declaration="yes"