Справка по запросу xpath, пытающаяся получить подмножество большего XML - PullRequest
0 голосов
/ 25 июня 2009

У меня есть большой набор XML, который я хотел бы запустить на xpath, чтобы превратить его в гораздо меньший поднабор. В принципе, у меня есть этот тип макета:

<root>
  <item>
    <collection1></collection1>
    <collection2></collection2>
    <collection3></collection3>
    ...
    <collection55></collection55>
    <name>item name</name>
    <timestamp>47398743598</timestamp>
    <another1></another1>
    <another2></another2>
    ...
  </item>
  <item>
   ...
  </item>
</root>

Другими словами, кучи узлов элементов и множество других нежелательных узлов, которые меня не интересуют.

Я хотел бы запустить xpath, чтобы получить значение:

<root>
  <item>
    <name>item name</name>
    <timestamp>47398743598</timestamp>
  </item>
  <item>
   ...
  </item>
</root>

В настоящее время у меня есть такие вещи:

// элемент / имя

, который получает только имена узлов,

Итак, я попробовал этот тип вещи:

// элемент / имя / родитель :: пункт

, который получает узлы имени и его родителя (который является узлом элемента), а также все узлы-узлы узла имени, чего я и пытаюсь избежать!

Любая помощь будет принята с благодарностью

Ура, Mark

Ответы [ 4 ]

4 голосов
/ 25 июня 2009

Прежде всего: вы не можете использовать XPath, чтобы получить XML-документ "до чего-то". Вы можете использовать его для выбора узлов, вот и все. Если вы хотите изменить XML-документ, используйте XSLT.

Это выражение:

//item/name/parent::item

не выбирает «имя узла и его родителя», оно выбирает родительские узлы <name> узлов и ничего больше.

Строго говоря, он выбирает все узлы <item>, которые являются родительскими для узла <name>, который сам является потомком узла <item>. Что эквивалентно использованию только "//item", когда вы думаете об этом.

Нет способа выбрать структуру узлов. Вы можете выбрать только список узлов - набор узлов. Затем вы можете пройти по этим узлам и выяснить их положение в документе, но сам набор узлов будет плоским.

Я думаю, вам нужно более подробно объяснить, что вы пытаетесь сделать. Я мог бы написать XSL-преобразование, которое выполняет то, что вы, похоже, намерены, но если я не уверен, что вы намерены ...; -)

EDIT:

Вот один минималистичный подход XSLT 1.0, который бы это сделал.

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

  <xsl:template match="root | item | name | timestamp">
    <xsl:copy>
      <xsl:apply-templates select="*" />
      <xsl:if test="count(*) = 0">
        <xsl:value-of select="text()" />
      </xsl:if>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="* | text()" />

</xsl:stylesheet>

Выход для вашего образца (шахта с отступами):

<root>e
  <item>
    <name>item name</name>
    <timestamp>47398743598</timestamp>
  </item>
  <item>
   ...
  </item>
</root>
1 голос
/ 29 июня 2009

Ответ Томалака хорош, если вы действительно хотите обрезанный XML-документ, но с одним предупреждением: его шаблон выбора будет копировать любой узел имени и метки времени, а не только те, которые находятся ниже элемента item.

Я подозреваю, однако, что вы на самом деле не хотите уточненный XML-документ, вам просто нужен узел имени и метки времени для каждого элемента. В зависимости от языка, который вы используете, вы должны быть в состоянии использовать xpath, чтобы дать вам меньший набор узлов для работы. В псевдо-коде:

  1. выберите xpath для "/ root / item". Это должно вернуть некоторый тип списка. Если Вы упоминаете свой язык реализации, я могу опубликовать простой фрагмент.
  2. Для каждого элемента выберите отметку времени и теги имен. Нет причин заботиться о других узлах.

Однако, если вы уверены, что хотите XML, используйте XSLT.

1 голос
/ 25 июня 2009

Используя XSLT, добавьте этот шаблон в преобразование идентичности :

<xsl:template match="item">
   <xsl:copy>
      <xsl:apply-templates select="name | timestamp"/>
   </xsl:copy>
</xsl:template>
0 голосов
/ 25 июня 2009

Вы можете попробовать с оператором or (|): //item/name|//item/timestamp

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...