【问题标题】:XSLT selecting text that contains strong tagsXSLT 选择包含强标签的文本
【发布时间】:2015-07-13 13:15:43
【问题描述】:

我正在尝试使用 XSLT 对一些 XML 进行转换。

我的 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>

但这仅适用于文本没有任何子级的情况,例如 &lt;strong&gt; 标记或另一个 &lt;a&gt; 标记。

有没有人可以解决所有问题。

【问题讨论】:

    标签: xml xslt


    【解决方案1】:

    我想出了这个 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>
    

    这个想法是复制&lt;p&gt;标签的内容,除了&lt;a&gt;标签。 我更改了第一个应用模板的条件,但您不必这样做。它只是让事情对我来说更具可读性。

    【讨论】:

    • 感谢您的回复。然而,这似乎并没有起到作用。我得到的回复是&lt;body&gt;&lt;p&gt;&lt;slideshow data-uuid="z3970z88-0475-11dz-8603-00144zeabdc1"/&gt;Some &lt;strong&gt;strong&lt;/strong&gt; text&lt;/p&gt;&lt;/body&gt; 当我只用文本尝试它并且没有强标签时它可以工作(但它在我之前的解决方案中适用于这种情况)。
    • 你还在使用你原来的状态吗?因为 count(*) 会阻止你匹配 p 标签。为什么需要这个计数?
    • 谢谢,你说得对,是计数停止了匹配。似乎不需要它,因为没有它通过其他测试。
    【解决方案2】:

    如果您只转换部分 XML,从 Identity Template 开始通常是一个不错的方法

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

    这意味着,不要在模板中使用xsl:value-of,而是使用xsl:apply-templates 并让身份模板

        <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>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-16
      • 1970-01-01
      相关资源
      最近更新 更多