How to select unique XML nodes using Ruby?

I have the following XML, I am trying to get unique nodes based on the name of the child node.

Original XML:

<products>
  <product>
    <name>White Socks</name>
    <price>2.00</price>
  </product>
  <product>
    <name>White Socks/name>
    <price>2.00</price>
  </product>
  <product>
    <name>Blue Socks</name>
    <price>3.00</price>
  </product>
</products>

What am I trying to get:

<products>
  <product>
    <name>White Socks</name>
    <price>2.00</price>
  </product>
  <product>
    <name>Blue Socks</name>
    <price>3.00</price>
  </product>
</products>

I tried different things, but not worth listing here, the closest I got was using XPath, but it just returned the names as shown below. However, this is not true since I want all of the XML to be listed above, and not just the node values.

White Socks
Blue Socks

I am using Ruby and trying to iterate over the following nodes:

@doc.xpath("//product").each do |node|

Obviously, the above is currently getting ALL product nodes, while I want all the unique nodes of the product (using the child node "name" as a unique identifier)

+3
source share
2 answers

:

<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:key name="kProdByName" match="product"
  use="name"/>

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

 <xsl:template match=
  "product
    [not(generate-id()
        =
         generate-id(key('kProdByName',name)[1])
         )
    ]"/>
</xsl:stylesheet>

XML- ( ):

<products>
    <product>
        <name>White Socks</name>
        <price>2.00</price>
    </product>
    <product>
        <name>White Socks</name>
        <price>2.00</price>
    </product>
    <product>
        <name>Blue Socks</name>
        <price>3.00</price>
    </product>
</products>

, :

<products>
  <product>
    <name>White Socks</name>
    <price>2.00</price>
  </product>
  <product>
    <name>Blue Socks</name>
    <price>3.00</price>
  </product>
</products>

:


XPath-one-liner ( , O (N ^ 2) - product):

 /*/product[not(name = following-sibling::product/name)]
+1

XSLT Muenchian :

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

  <xsl:key name="prod-by-name" match="product" use="name"/>

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

  <xsl:template match="product[not(generate-id() = generate-id(key('prod-by-name', name)[1]))]"/>

</xsl:stylesheet>
0

Source: https://habr.com/ru/post/1792581/


All Articles