XPath 1.0:选择具有给定父节点的所有子节点,如果父节点没有这样的子节点,则选择空?

时间:2013-02-05 14:42:01

标签: xpath vtd-xml

使用XPath 1.0和下面的XML,如何选择具有“b”父级的所有“c”节点,如果“b”父级没有“c”节点,则选择“”,即get {{ 1}}作为结果节点集(按文档顺序)?

我正在使用VTD-XML 2.11(Java),我正在寻找一个单独的XPath评估,它将返回上述结果而不会循环。

{"c1", "", "c3"}

我已经浏览过这些问题并找到了有趣的指针,例如Oliver Becker的方法,但到目前为止我还没有找到解决方案。

任何帮助都将不胜感激。

感谢。

2 个答案:

答案 0 :(得分:1)

您使用什么来评估这些XPath?我无法想出一个好方法,但根据您使用它的方法,可以很容易地选择所有b,迭代它们,并使用c或a的值每个空白值。

这不是一个很好的方法,但它适用于您的样本输入:

//b/c | //b[not(*)] | //b[not(c) and *]/text()

解释是:

  • 选择c
  • 下的所有b
  • 如果没有子元素,则选择任何b个元素
  • 选择没有b个孩子的任何c的第一个文本节点。

这将假设任何带有子元素的b将至少有一个文本节点,并且其中第一个将完全是空格。

使用XSLT进行验证:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="/">
    <root>
      <xsl:for-each select="//b/c | //b[not(*)] | //b[not(c) and *]/text()[1]">
        <item>
          <xsl:value-of select="."/>
        </item>
      </xsl:for-each>
    </root>
  </xsl:template>
</xsl:stylesheet>

在样本输入上运行时的输出:

<root>
  <item>c1</item>
  <item></item>
  <item>c3</item>
</root>

答案 1 :(得分:0)

这样的东西?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.XPath;
using System.IO;

namespace Xpath
{
    class Program
    {
        static void Main(string[] args)
        {

            string xml = @"<a>
              <b>
                <c>c1</c>
              </b>
              <b/>
              <b>
                <c>c3</c>
              </b>
              <b>x</b>
            </a>";

            XmlDocument doc = new XmlDocument();
            doc.LoadXml(xml);

            string xpath = "//b/c/text()|//b[count(child::*) = 0]|//b[count(child::*) = 0]/text()";

            StringReader stringReader = new StringReader(xml);
            XmlReader xmlReader = XmlReader.Create(stringReader);

            XPathDocument xpathDoc = new XPathDocument(xmlReader);

            XPathNavigator xpathNav = xpathDoc.CreateNavigator();
            XPathNodeIterator xpathIter = xpathNav.Select(xpath);

            foreach (XPathNavigator navigator in xpathIter)
            {
                if (navigator.ValueType == typeof(string))
                {
                    Console.WriteLine("'" + navigator.Value + "'");
                }
            }
        }
    }
}

输出是:

'c1'
''
'c3'
'x'