2015-07-13 40 views
0

我正在尝试使用XSLT对某些XML进行转换。选择包含强标记的文本的XSLT

我的xml是;

<body> 
     <p> 
     <a href="http://www.zz.com/abc/z/0/z3970z88-0475-11dz-8603-00144zeabdc1.html#slide0"></a> 
     Some <strong>strong</strong> text 
     </p> 
    </body> 

我想将它转换为;

<body> 
     <slideshow data-uuid="z3970z88-0475-11dz-8603-00144zeabdc1/> 
     <p>Some <strong>strong</strong> text</p> 
    </body> 

我到目前为止是什么;

<xsl:template match="/body/p[a[substring(@href, string-length(@href) - 6) = '#slide0' and string-length(text()) = 0] and count(*) = 1]"> 
     <xsl:apply-templates select="a" /> 
     <xsl:if test="string-length(text()) > 0"> 
     <p> 
      <xsl:value-of select="text()"/> 
     </p> 
     </xsl:if> 
    </xsl:template> 

    <xsl:template match="a[substring(@href, string-length(@href) - 6) = '#slide0' and string-length(text()) = 0]"> 
     <slideshow> 
     <xsl:attribute name="data-uuid"> 
      <xsl:value-of select="substring-before(substring(@href, string-length(@href) - 47), '.html#slide0')" /> 
     </xsl:attribute> 
    </xsl:template> 

但是,如果文本没有任何子女,如<strong>标签或其他<a>标签这仅适用。

有没有人有一个解决方案,将它挑起来。

回答

0

我想出了这个XSLT。我不知道如果要是将适应各种目的,你可以拿出,但它确实解决了你给这里的例子:

<?xml version="1.0"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:template match="/body/p[a]"> 
     <xsl:apply-templates select="a" /> 
     <p> 
      <xsl:copy-of select="./node()[not(self::a)]" /> 
     </p> 
    </xsl:template> 

    <xsl:template match="a[substring(@href, string-length(@href) - 6) = '#slide0' and string-length(text()) = 0]"> 
     <slideshow> 
      <xsl:attribute name="data-uuid"> 
       <xsl:value-of select="substring-before(substring(@href, string-length(@href) - 47), '.html#slide0')" /> 
      </xsl:attribute> 
     </slideshow> 
    </xsl:template> 
</xsl:stylesheet> 

的想法是复制<p>标签的内容期望<a>标签。 我改变了第一个应用模板的条件,但你不必这样做。它只是让我的东西更具可读性。

+0

感谢您的答复。然而,这似乎并没有诀窍。我得到的答复是'

<幻灯片数据的UUID =“z3970z88-0475-11dz-8603-00144zeabdc1” />有些文本

'当我只有文字而没有强烈的触杀尝试它的工作原理(但它在我以前的解决方案中用于这种情况)。 –

+0

你还在使用你的原始状态吗?因为count(*)会阻止您匹配p标签。为什么需要这个计数? – cvesters

+0

谢谢,你是对的,这是计数停止匹配。似乎没有必要,因为没有它的其他测试通过。 –

0

在您要变换只是你的XML的一部分的情况下,通常是先从Identity Template

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

这意味着,而不是在你的模板使用xsl:value-of,使用xsl:apply-templates,让一个好方法身份TEMPL

<xsl:if test="string-length(text()) > 0"> 
     <p> 
      <xsl:apply-templates select="@*|node()[not(self::a)]"/> 
     </p> 
    </xsl:if> 

试试这个XSLT

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

    <xsl:template match="p[a[substring(@href, string-length(@href) - 6) = '#slide0' and string-length(text()) = 0] and count(*) = 1]"> 
     <xsl:apply-templates select="a" mode="slideshow" /> 
     <xsl:if test="string-length(text()) > 0"> 
      <p> 
       <xsl:apply-templates select="@*|node()[not(self::a)]"/> 
      </p> 
     </xsl:if> 
    </xsl:template> 

    <xsl:template match="a" mode="slideshow"> 
     <slideshow> 
     <xsl:attribute name="data-uuid"> 
      <xsl:value-of select="substring-before(substring(@href, string-length(@href) - 47), '.html#slide0')" /> 
     </xsl:attribute> 
     </slideshow> 
    </xsl:template> 

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

请注意在匹配a的模板中使用“模式”。这纯粹是为了避免必须对冗长的条件编码两次。

顺便说一句,你在a模板中使用Attribute Value Templates,简化它

<xsl:template match="a" mode="slideshow"> 
     <slideshow data-uuid="{substring-before(substring(@href, string-length(@href) - 47), '.html#slide0')}" /> 
</xsl:template>