2015-03-11 8 views
0

Я пытаюсь проанализировать XML-файлы и создать CSV определенных значений. Ниже приведен пример XML-файл:. http://forecast.weather.gov/MapClick.php?lat=31.7815&lon=-84.3711&FcstType=digitalDWMLXMLStarlet: объединить значения узлов от разных родителей на основе позиционного индекса

Файл XML имеет два различных типа узлов, что я заинтересован в

  1. В start-valid-time узлы (//start-valid-time)
  2. coverage атрибут value узлов, которые дон 't имеет атрибут additional (//weather-conditions/value[not(@additive)]/@coverage).

Узлы связаны не гнездом, а положением. Первый узел start-valid-time соответствует первому атрибуту //weather-conditions/value[[email protected])]/@coverage.

Я хотел бы вывести start-valid-time, а затем запятую, а затем соответствующий атрибут coverage.

например

2015-03-11T14:00:00-04:00, chance 2015-03-11T15:00:00-04:00, chance ... 2015-03-12T03:00:00-04:00, slight chance

, которые я пытался различные xmlstarlet команды безрезультатно.

Вот один:

xmlstarlet sel -T -t -m "//weather-conditions/value[not(@additive)]" -v "//start-valid-time" -v "@coverage" -n XML 

Возможно, я ближе с этой командой:

xmlstarlet sel -T -t -m "//start-valid-time" -v "concat(current(),',',//weather-conditions[count(preceding-sibling::start-valid-time)+1]/value/@coverage)" -n XML 

Однако значения атрибута coverage, кажется, все будет от его первой инстанции.

Буду признателен за помощь в этом!

+0

Эта ссылка никуда не ведет, если я не ошибаюсь. –

+0

Нечетный - он работал секунду назад. Я обновил его. Теперь он работает снова. –

ответ

2

Это очень сложный вызов только в XPath, но он прост в XSLT.

<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
    <xsl:output method="text" encoding="UTF-8" /> 

    <xsl:variable name="weatherCond" select="//weather-conditions/value[not(@additive)]" /> 

    <xsl:template match="/"> 
    <xsl:for-each select="//start-valid-time"> 
     <xsl:variable name="myPos" select="position()" /> 
     <xsl:value-of select="." /> 
     <xsl:text>,</xsl:text> 
     <xsl:value-of select="$weatherCond[position() = $myPos]/@coverage" /> 
     <xsl:value-of select="'&#xA;'" /> 
    </xsl:for-each> 
    </xsl:template> 
</xsl:transform> 

выходы

 
2015-03-11T17:00:00-04:00,chance 
2015-03-11T18:00:00-04:00,chance 
2015-03-11T19:00:00-04:00,chance 
2015-03-11T20:00:00-04:00,chance 
2015-03-11T21:00:00-04:00,chance 
2015-03-11T22:00:00-04:00,chance 
2015-03-11T23:00:00-04:00,chance 
2015-03-12T00:00:00-04:00,chance 
2015-03-12T01:00:00-04:00,chance 
2015-03-12T02:00:00-04:00,slight chance 
2015-03-12T03:00:00-04:00,slight chance 
2015-03-12T04:00:00-04:00,slight chance 
... 

То есть, я полагаю, вы можете также просто использовать два основных XMLStarlet выбора команд и join their outputs line-wise.

+0

Отлично. Как бы изменить @coverage на конкатенирование обоих значений узлов (если существует тот, который содержит аддитивный параметр)? –

+0

Если для значения может быть только один параметр добавки, просто используйте '', чтобы проверить его, а затем вывести его с помощью < 'внутри' if'. Если может быть больше, все становится немного сложнее. – Tomalak

+5

Эквивалентная команда xmlstarlet должна быть «xmlstarlet sel -T -t -var» weatherCond = // weather-conditions/value [not (@additive)] '-m // start-valid-time --var' myPos = position() '-v. -o, -v '$ weatherCond [position() = $ myPos]/@ coverage' -n', подставлять '' 'для' '' при использовании 'cmd.exe'. – npostavs