【问题标题】:Copy node and alter its content复制节点并更改其内容
【发布时间】:2014-03-20 09:10:05
【问题描述】:

我有点卡在我想对 xml 文件进行的转换上。

基本上我正在尝试复制所有的 xml,但更改一些标签,这些标签只能这样开始

XML 代码:

<test alt="foo" title="bar"/>

通过 xsl 后我想得到什么:

<test alt="foo"/>

或者

<change alt="foo" title=""/>

问题是,有时我的标签有很多属性,所以我不想进行模板匹配,然后手动更改每个属性。

其实我就是这样做的:

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

<xsl:template match="test/@title">
    <xsl:attribute name="title">
        <xsl:value-of select=""/>
    </xsl:attribute>
</xsl:template>

但它不会改变输出中标题的内容。

【问题讨论】:

    标签: xml xslt transformation


    【解决方案1】:

    对于所有此类任务,您应该从身份转换模板开始

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

    然后为需要特殊处理的节点添加模板,例如

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

    将复制所有未更改的内容,但会删除 test 元素的所有 title 属性。

    或者

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

    应该实现您的第二个要求。如果您仍有问题,请发布最少但完整的示例,以便我们重现问题。

    【讨论】:

    • 感谢它成功了!现在假设我有一个 xhtml 文件,所以我得到了 围绕我的其余标签。我应该使用哪个路径来制作与 相同的东西? (html/test/@title 似乎不起作用)
    • 匹配模式的好处是在大多数情况下您不需要指定完整路径,例如match="test/@title" 将处理所有test 元素的所有title 属性,独立于test 可能具有的任何祖先。如果您想限制治疗,您可以使用例如match="body/div[@class = 'foo']/test/@title" 仅处理div 元素中test 元素的title 属性,其中classfoo,它们是body 元素的直接子元素。当然,XHTML 通常有一个命名空间,它总是使 XPath 变得复杂。
    • 如果您仍然遇到 XHTML 输入问题,最好使用显示任何命名空间的 X(HT)ML 示例提出一个新问题。
    • 再次感谢,如果我遇到任何问题,我会这样做
    【解决方案2】:

    要删除除alt 之外的任何属性,请使用身份转换,但有一个例外:

    样式表(移除其他属性)

    <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="@*|node()">
              <xsl:copy>
                 <xsl:apply-templates select="@*|node()"/>
              </xsl:copy>
        </xsl:template>
    
        <xsl:template match="@*[name() != 'alt']"/>
    
    </xsl:stylesheet>
    

    输出

    <?xml version="1.0" encoding="utf-8"?>
    <test alt="foo"/>
    

    否则,要将除alt 之外的所有属性的值设置为"",请使用:

    样式表(使其他属性为空)

    <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="@*|node()">
              <xsl:copy>
                 <xsl:apply-templates select="@*|node()"/>
              </xsl:copy>
        </xsl:template>
    
        <xsl:template match="test">
            <change>
                <xsl:apply-templates select="@*|node()"/>
            </change>
        </xsl:template>
    
        <xsl:template match="@*[name() != 'alt']">
            <xsl:attribute name="{name()}"/>
        </xsl:template>
    
    </xsl:stylesheet>
    

    输出

    <?xml version="1.0" encoding="utf-8"?>
    <change alt="foo" title=""/>
    

    【讨论】:

    • 感谢您的输入,但 Martin 的回答最适合我的需要,因为它指定了一个标签的更改,除非 @*[name() != 'alt'] 会将除 alt 之外的所有标签设置为“ "
    猜你喜欢
    • 1970-01-01
    • 2016-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-16
    • 1970-01-01
    • 1970-01-01
    • 2014-06-13
    相关资源
    最近更新 更多