Как выбрать уникальные XML-узлы, используя Ruby? - PullRequest
3 голосов
/ 16 февраля 2011

У меня есть следующий XML, я пытаюсь получить уникальные узлы на основе имени дочернего узла.

Исходный 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, но он только что возвратил имена, как показано ниже.Однако это неправильно, так как я хочу полный XML, как указано выше, а не только значения узлов.

White Socks
Blue Socks

Я использую Ruby и пытаюсь перебирать узлы следующим образом:

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

Очевидно, что вышеприведенное в настоящее время получает ВСЕ узлы продукта, тогда как я хочу, чтобы все уникальные узлы продукта (с использованием дочернего узла "имя" в качестве уникального идентификатора)

Ответы [ 2 ]

1 голос
/ 16 февраля 2011

Это преобразование :

<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>

Примечание :

  1. правило идентификации копирует каждый узел "как есть".

  2. Используется мюнхенский метод группировки .

  3. Существует один переопределяющий шаблон, который исключает любой элемент product, который не является первым в его группе.


XPath-one-liner (Обратите внимание, что это O (N ^ 2) - будет очень медленным на многих product элементах):

 /*/product[not(name = following-sibling::product/name)]
0 голосов
/ 16 февраля 2011

С XSLT вы можете использовать мюнхенскую группировку для устранения дубликатов следующим образом:

<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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...