XML返回所有节点名称包含子字符串

时间:2015-04-11 19:30:41

标签: xml xpath xquery

由于我是XPath / XQuery的新手,并且尝试查询大量的xml文件数据,所以我想,也许有人可以帮我解决这个问题。

我有一个xml数据,如下所示:

<financial_statement>
  <revenue>123</revenue>
  <interestRevenue>234</interestRevenue>
  <salaries>12<salaries>
  <transactionRevenue>345</transactionRevenue>
  <revenueOtherServices>109</revenueOtherServices>
  <sales>783</sales>
  <costs>746</costs>
  .....
</financial_statement>

我想查询此xml数据并仅返回包含字符串&#34; revenue&#34;在他们的名字。所以输出应该如下:

<revenue>
  <revenue>123</revenue>
  <interestRevenue>234</interestRevenue>
  <transactionRevenue>345</transactionRevenue>
  <revenueOtherServices>109</revenueOtherServices>
</revenue>

其实我没有使用编程语言。我有一个在eXist本地运行的XML数据库,它包含一个内置的XQuery引擎。因此,我正在寻找XPath / XQuery代码。

提前致谢!

2 个答案:

答案 0 :(得分:1)

XQuery解决方案可能如下所示。返回最外面的元素revenue,并查找名称中包含&#34; revenue&#34;(小写或大写)的所有元素,它们是translate()函数的作用。

这里,输入文档被分配给变量$x,但您也可以使用doc()函数或任何其他方法来检索由eXist提供的XML数据。

<强>的XQuery

let $x := <financial_statement><revenue>123</revenue><interestRevenue>234</interestRevenue><salaries>12</salaries><transactionRevenue>345</transactionRevenue><revenueOtherServices>109</revenueOtherServices><sales>783</sales><costs>746</costs></financial_statement>

return <revenue>{$x//*[contains(translate(name(),'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'),'revenue')]}</revenue>

使用translate()可保证XPath 1.0的可移植性,但由于XQuery使用XPath 2.0,您还可以使用lower-case()upper-case()来模仿不区分大小写的contains()函数。

XML输出

<revenue>
   <revenue>123</revenue>
   <interestRevenue>234</interestRevenue>
   <transactionRevenue>345</transactionRevenue>
   <revenueOtherServices>109</revenueOtherServices>
</revenue>

如果您真的要求XSLT解决方案,以下转换可以满足您的需求。由于XQuery和XSLT都使用XPath,因此方法几乎相同。

XML输入

<financial_statement>
  <revenue>123</revenue>
  <interestRevenue>234</interestRevenue>
  <salaries>12</salaries>
  <transactionRevenue>345</transactionRevenue>
  <revenueOtherServices>109</revenueOtherServices>
  <sales>783</sales>
  <costs>746</costs>
</financial_statement>

XSLT样式表

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
    <xsl:output method="xml" omit-xml-declaration="yes" encoding="UTF-8" indent="yes" />

    <xsl:template match="/">
      <revenue>
          <xsl:apply-templates/>
      </revenue>
    </xsl:template>

    <xsl:template match="*[contains(translate(name(),'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'),'revenue')]">
        <xsl:copy-of select="."/>
    </xsl:template>

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

XML输出

<revenue>
   <revenue>123</revenue>
   <interestRevenue>234</interestRevenue>
   <transactionRevenue>345</transactionRevenue>
   <revenueOtherServices>109</revenueOtherServices>
</revenue>

  

其实我没有使用编程语言。

嗯,你知道,XQuery 一种编程语言。在我看来,就是这样。

答案 1 :(得分:-1)

您可以使用name功能。这是一个XSLT 1.0解决方案。

<?xml version='1.0' encoding='UTF-8'?>

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" encoding="utf-8"/>

  <xsl:template match="*">
    <xsl:variable name="n" select="name (.)"/>
    <xsl:element name="{$n}">
      <xsl:for-each select="@*">
        <xsl:copy-of select="."/>
      </xsl:for-each>
      <xsl:apply-templates select="node()"/>
    </xsl:element>
  </xsl:template>

  <xsl:template match="text()">
    <xsl:value-of select="."/>
  </xsl:template>

  <xsl:template match="/">
    <xsl:element name="revenue">
      <xsl:apply-templates select="financial_statement"/>
    </xsl:element>
  </xsl:template>

  <xsl:template match="financial_statement">
    <xsl:for-each select="*">
      <xsl:variable name="n" select="name (.)"/>
      <xsl:if test="contains ($n, &quot;revenue&quot;) or contains ($n, &quot;Revenue&quot;)">
        <xsl:apply-templates select="."/>
      </xsl:if>
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>

这为您的示例提供了所需的输出。