XPATH表达式输出父节点和匹配的子节点,不包括不匹配的子节点

时间:2012-11-05 20:29:32

标签: java xslt xpath xslt-1.0

下面是XML

<?xml version="1.0" encoding="UTF-8"?>
<library>
    <object>book</object>
    <bookname>
        <value>testbook</value>
        <author>
            <value>ABCD</value>
            <category>
                <value>story</value>
                <price>
                    <dollars>200</dollars>
                </price>
            </category>
        </author>
        <author>
            <value>EFGH</value>
            <category>
                <value>fiction</value>
                <price>
                    <dollars>300</dollars>
                </price>
            </category>
        </author>
    </bookname>
</library>

我需要xpath表达式来获得以下输出

<?xml version="1.0" encoding="UTF-8"?>
<library>
    <object>book</object>
    <bookname>
        <value>testbook</value>
        <author>
            <value>ABCD</value>
            <category>
                <value>story</value>
                <price>
                    <dollars>200</dollars>
                </price>
            </category>
        </author>
    </bookname>
</library>

但是当我应用下面的xpath表达式时,我将整个输入xml作为转换输出。相反,我只需要父节点+子节点匹配author / value ='ABCD'(如上所示)

<xsl:copy-of select="/library/object[text()='book']/../bookname/value[text()='testbook']/../author/value[text()='ABCD']/../../.."/>

请帮助我使用正确的xpath表达式来获得所需的输出。

我正在使用java程序来评估xpath表达式以获得我想要的XML输出。所以我需要一个xpath表达式。下面是我的java代码

DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
domFactory.setNamespaceAware(true);
DocumentBuilder builder = domFactory.newDocumentBuilder();
Document doc = builder.parse("books.xml");

XPathFactory factory = XPathFactory.newInstance();
XPath xpath = factory.newXPath();
XPathExpression expr = xpath.compile("/library/object[text()='book']/../bookname/value[text()='testbook']/../author/value[text()='ABCD']/../../..");

Object result = expr.evaluate(doc, XPathConstants.NODESET);
NodeList nodes = (NodeList) result;

请在 Java或xslt

中帮助我找到正确的解决方案

1 个答案:

答案 0 :(得分:2)

你不能在纯xpath中执行此操作。

此样式表将在XSL 2.0中执行您想要的操作

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

  <!-- Idendtity template -->
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="author[not(value eq 'ABCD')]"/>

</xsl:stylesheet>

此样式表将在XSL 1.0中执行您想要的操作

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

  <!-- Idendtity template -->
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="author[not(value = 'ABCD')]"/>

</xsl:stylesheet>