#xml #xslt #xquery
#xml #xslt #xquery
Вопрос:
Вот мой xml
<book asin="0201100886"
created="128135928"
lastLookupTime="128135928">
<price>102.00</price>
<purchaseDate>2005-01-22</purchaseDate>
</book>
<book asin="0122513363" created="128135600" lastLookupTime="128136224">
<price>50.95</price>
<purchaseDate>2005-01-22</purchaseDate>
</book>
<book asin="0201441241"
created="128136896"
lastLookupTime="128136896">
<price>108.20</price>
<purchaseDate>2005-01-22</purchaseDate>
</book>
<book asin="0471250600"
created="128136896"
lastLookupTime="128136896">
<price>107.95</price>
<purchaseDate>2005-01-22</purchaseDate>
</book>
<book asin="0321193628"
created="128136896"
lastLookupTime="128136896">
<price>112.40</price>
</book>
Мне нужно обновить цены на все книги на 0,50 цента. Как я могу это сделать?
Комментарии:
1. Обязательно ли это делать с помощью XQuery или вы можете использовать XSLT?
2. Хороший вопрос, 1. Смотрите мой ответ для рекомендации и полного, очень короткого решения XSLT 🙂
Ответ №1:
Если вы ищете решение, используя средство обновления XQuery:
for $p in //price return
replace value of node $p with $p 0.50
Комментарии:
1. Изменит ли это мой существующий xml?
Ответ №2:
В XQuery для выполнения преобразования используется рекурсивная функция.
declare function local:reprice($nodes as node()*) {
for $node in $nodes
return
typeswitch($node)
case element(price)
return element price {xs:decimal($node) 0.5}
case element(
return
element {name($node)} {
$node/@*,
local:reprice($node/node())}
default
return $node
};
тогда, если на документ books ссылаются как на $books:
local:reprice($books)
Дальнейшее обсуждение и примеры в http://en.wikibooks.org/wiki/XQuery/Typeswitch_Transformations.
В качестве альтернативы используйте базу данных XML, такую как eXist-db, и обновите institu:
for $price in $books//price
let $newprice := xs:decimal($price) 0.5
return update replace $price with elememt price {$newprice}
Обратите внимание, что расширения обновления XQuery в основном зависят от реализации, пока обновление XQuery не получит более широкой поддержки
Ответ №3:
XSLT значительно более подходит для использования, чем XQuery, для такого рода задач:
Это преобразование:
<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:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="price/text()">
<xsl:value-of select="format-number(. 0.50, '##0.00')"/>
</xsl:template>
</xsl:stylesheet>
при применении к предоставленному XML-документу:
<books>
<book asin="0201100886" created="128135928" lastLookupTime="128135928">
<price>102.00</price>
<purchaseDate>2005-01-22</purchaseDate>
</book>
<book asin="0122513363" created="128135600" lastLookupTime="128136224">
<price>50.95</price>
<purchaseDate>2005-01-22</purchaseDate>
</book>
<book asin="0201441241" created="128136896" lastLookupTime="128136896">
<price>108.20</price>
<purchaseDate>2005-01-22</purchaseDate>
</book>
<book asin="0471250600" created="128136896" lastLookupTime="128136896">
<price>107.95</price>
<purchaseDate>2005-01-22</purchaseDate>
</book>
<book asin="0321193628" created="128136896" lastLookupTime="128136896">
<price>112.40</price>
</book>
</books>
выдает желаемый, правильный результат:
<books>
<book asin="0201100886" created="128135928" lastLookupTime="128135928">
<price>102.50</price>
<purchaseDate>2005-01-22</purchaseDate>
</book>
<book asin="0122513363" created="128135600" lastLookupTime="128136224">
<price>51.45</price>
<purchaseDate>2005-01-22</purchaseDate>
</book>
<book asin="0201441241" created="128136896" lastLookupTime="128136896">
<price>108.70</price>
<purchaseDate>2005-01-22</purchaseDate>
</book>
<book asin="0471250600" created="128136896" lastLookupTime="128136896">
<price>108.45</price>
<purchaseDate>2005-01-22</purchaseDate>
</book>
<book asin="0321193628" created="128136896" lastLookupTime="128136896">
<price>112.90</price>
</book>
</books>
Комментарии:
1. Я должен использовать XQuery и изменить существующий xml. xslt довольно гладкий, и я хотел бы им воспользоваться : (
2. @zach: В XQuery есть что-то вроде
typeswitch
(никогда не имел несчастья использовать это) — прочитайте об этом и используйте. Это очень примитивный механизм сопоставления, который мог бы в некоторой степени помочь. w3.org/TR/xquery/#id-typeswitch