如何从XML中的许多节点中选择一些节点以及该节点的文本或属性值

时间:2014-03-12 06:53:06

标签: xml xslt xslt-1.0

我有一个复杂的XML,这里给出了简化版本。 我想要实现的是仅从给定的节点集获取数据(文本或属性值) 在XML中。许多示例仅适用于XPATH。但我的XML结构很复杂,我想使用递归方法扫描节点而不是硬编码XPATH。

INPUT:

<Root>
    <Book>
    <Content >
    <Chapter id="1" startpage="1" endpage="20">
        <Topic id="1">
        <Title>Title1</Title>
        <Content>Paragraphs</Content>
        </Topic>
        <Topic id="1.1">
        <Title>Title1.1</Title>
        <Content>Paragraphs</Content>
        </Topic>
        <Topic id="1.2">
        <Title>Title1.2</Title>
        <Content>Paragraphs</Content>
        </Topic>
    </Chapter>
    <Chapter id="2" startpage="21" endpage="90">
        <Topic id="2">
        <Title>Title2</Title>
        <Content>Paragraphs</Content>
        </Topic>
        <Topic id="2.1">
        <Title>Title2.1</Title>
        <Content>Paragraphs</Content>
        </Topic>
        <Topic id="2.1.2">
        <Title>Title2.1.2</Title>
        <Content>Paragraphs</Content>
        </Topic>
    </Chapter>
    <Index>
    Some more nodes here
    </Index>
             </Content>
    </Book>
</Root>

期望的输出:

<Root>
<Book>
<Content>
    <Chapter id="1" startpage="1" endpage="20">

    <Title>Title1</Title>

    <Title>Title1.1</Title>

    <Title>Title1.2</Title>

    </Chapter>
<Chapter id="2" startpage="21" endpage="90">

    <Title>Title2</Title>

    <Title>Title2.1</Title>

    <Title>Title2.1.2</Title>

</Chapter>

</Book>
</Root>

CURRENT XSL:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ns="some:ns">
   <xsl:output omit-xml-declaration="yes" indent="yes"/>
   <xsl:strip-space elements="*"/>

   <ns:WhiteList>
      <name>Root</name>
      <name>Book</name>
      <name>Chapter</name>
      <name>Title</name> 
   </ns:WhiteList>

   <xsl:variable name="whistList" select="document('')/*/ns:WhiteList" />

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

   <xsl:template match="@*">
      <xsl:if test="attribute::*[name()=$whistList/*]">
         <xsl:copy/>

      </xsl:if>
   </xsl:template>   

     <xsl:template match="*">
      <xsl:if test="descendant-or-self::*[name()=$whistList/*]">
         <xsl:copy>
             <xsl:value-of select="node()" />
            <xsl:apply-templates select="@*|node()"/>
         </xsl:copy>

      </xsl:if>
   </xsl:template>
</xsl:stylesheet>

3 个答案:

答案 0 :(得分:1)

我已将以下内容添加到您的样式表中:

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

,输出现在是

<Root>
   <Book>
      <Content>
         <Chapter>
            <id>1</id>
            <startpage>1</startpage>
            <endpage>20</endpage>
            <Title>Title1</Title>
            <Title>Title1.1</Title>
            <Title>Title1.2</Title>
         </Chapter>
         <Chapter>
            <id>2</id>
            <startpage>21</startpage>
            <endpage>90</endpage>
            <Title>Title2</Title>
            <Title>Title2.1</Title>
            <Title>Title2.1.2</Title>
         </Chapter>
      </Content>
   </Book>
</Root>

答案 1 :(得分:0)

看起来这个工作正常。但是,它仍然显示我不想要的节点。我相信这是因为节点中有一个属性。

 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ns="some:ns">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>
    <xsl:strip-space elements="*"/>
    <ns:WhiteList>
            <elename>Chapter</elename>
            <elename>Title</elename>
    </ns:WhiteList>
    <xsl:variable name="whistList" select="document('')/*/ns:WhiteList" />

    <xsl:template match="node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="@*">
        <xsl:copy>
            <xsl:call-template name="flatattr"/>
            <xsl:apply-templates/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="@*" name="flatattr">
        <xsl:element name="{local-name()}">
            <xsl:value-of select="."/>
        </xsl:element>
    </xsl:template>
    <xsl:template match="*">
        <xsl:if test="descendant-or-self::*[name()=$whistList/*]">
            <xsl:copy>
                <xsl:apply-templates select="@*|node()"/>
            </xsl:copy>
        </xsl:if>
    </xsl:template>
    <xsl:template match="Expression[ancestor::Expression]">
        <xsl:apply-templates />
    </xsl:template>
    <xsl:template match="SimpleExpression">
        <xsl:text>(</xsl:text>
        <xsl:apply-templates />
        <xsl:text>)</xsl:text>
    </xsl:template>
    <xsl:template match="ValueExpression|Operator">
        <xsl:text>(</xsl:text>
        <xsl:value-of select="." />
        <xsl:text>)</xsl:text>
    </xsl:template>
</xsl:stylesheet>

答案 2 :(得分:0)

如果决定因素是节点的名称(无论节点的路径如何),您可以尝试:

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

<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:variable name="whiteList">
    <name>Root</name>
    <name>Book</name>
    <name>Chapter</name>
    <name>Title</name>
    <name>id</name>
</xsl:variable>
<xsl:variable name="whiteListSet" select="exsl:node-set($whiteList)/name" />

<xsl:template match="*">
    <xsl:choose>
        <xsl:when test="name()=$whiteListSet">
            <xsl:copy>
                <xsl:apply-templates select="@*|node()"/>
            </xsl:copy>
        </xsl:when>
        <xsl:otherwise>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

<xsl:template match="@*">
    <xsl:if test="name()=$whiteListSet and name(parent::*)=$whiteListSet">
        <xsl:copy/>
    </xsl:if>
</xsl:template>

<xsl:template match="text()">
    <xsl:if test="name(parent::*)=$whiteListSet">
        <xsl:copy/>
    </xsl:if>
</xsl:template>

</xsl:stylesheet>

当上述内容应用于您的示例输入时,结果为:

<?xml version="1.0" encoding="UTF-8"?>
<Root>
   <Book>
      <Chapter id="1">
         <Title>Title1</Title>
         <Title>Title1.1</Title>
         <Title>Title1.2</Title>
      </Chapter>
      <Chapter id="2">
         <Title>Title2</Title>
         <Title>Title2.1</Title>
         <Title>Title2.1.2</Title>
      </Chapter>
   </Book>
</Root>