无法使用XPath访问文本块

时间:2016-06-12 13:12:45

标签: xml xslt xpath

我有一个XML文件,我想使用XSLT进行转换。我们的想法是将每个<paragraph/>代码前的所有内容放入<p></p>代码中。

XML文件:

<section>
    Hello everyone, I'm
    <bold>Hackmania</bold>
    <bold>15</bold>
    <line/>
    I am looking for an
    <highlight>answer</highlight>
    <paragraph/>

    Here is an other
    <bold>paragraph</bold>
    <highlight>with the same tags</highlight>
    <paragraph/>
</section>

想要改造XML:

<section>
    <p>
        Hello everyone, I'm
        <bold>Hackmania</bold>
        <bold>15</bold>
        <line/>
        I am looking for an
        <highlight>answer</highlight>
    </p>
    <p>
        HHere is an other
        <bold>paragraph</bold>
        <highlight>with the same tags</highlight>
    </p>
</section>

这是我的XSL文件:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet>
    <xsl:template match="/">
        <section>
            <xsl:apply-templates/>
        </section>
    </xsl:template>

    <xsl:template match="paragraph">
        <xsl:for-each select=".">
            <p>
                <xsl:apply-templates select="/*/*[preceding-sibling::paragraph]"/>
            </p>
        </xsl:for-each>

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

先谢谢你的帮助。

2 个答案:

答案 0 :(得分:1)

我愿意:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:key name="grpById" match="node()[not(self::paragraph)]" use="generate-id(following-sibling::paragraph[1])" />

<xsl:template match="/section">
    <xsl:copy>
        <xsl:for-each select="paragraph">
            <p>
                <xsl:copy-of select="key('grpById', generate-id())"/>
            </p>
        </xsl:for-each>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

如果您可以使用XSLT 2.0,那么:

XSLT 2.0

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

<xsl:template match="/section">
    <xsl:copy>
        <xsl:for-each-group select="node()" group-ending-with="paragraph">
            <p>
                <xsl:copy-of select="current-group()[not(self::paragraph)]" />
            </p>
        </xsl:for-each-group>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

答案 1 :(得分:0)

尝试这样的事情:

<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes" encoding="UTF-8"/>
  <xsl:strip-space elements="*"/>
    <xsl:template match="@*|node()">
          <xsl:copy>
              <xsl:apply-templates select="node()"/>
          </xsl:copy>  
    </xsl:template>
    <xsl:template match="section">
        <xsl:apply-templates select="paragraph"/>
    </xsl:template>
  <xsl:template match="paragraph">
    <xsl:variable name="this" select="." />
    <p>
     <xsl:apply-templates select="preceding-sibling::node()[not(self::paragraph) 
                           and generate-id(following-sibling::paragraph) = 
                               generate-id($this)]" />
    </p>
  </xsl:template>
</xsl:stylesheet>

但请注意,如果最后一段之后有内容,则上述内容将失败。要处理该更改,请将部分模板更改为:

    <xsl:template match="section">
        <xsl:apply-templates select="paragraph"/>
        <xsl:apply-templates select="paragraph[last()]/following-sibling::node()"/>
    </xsl:template>