如何(以最方便的方式)替换xml文件中给定名称的所有属性?

时间:2018-03-16 03:04:43

标签: xml xslt lxml

假设我有一些包含这样的xml输入。 w15可能还有其他内容,例如ww1

<w15:presenceInfo w15:providerId="None" w15:userId="First Last"/>

有人知道替换的最佳方式是什么?

w15:userId =&#34; First Last&#34; - &GT; w15:userId =&#34;其他东西&#34;

我不想使用像sed这样的东西,因为我害怕更换一些不应该替换的东西。

有人知道xslt中的解决方案吗?

有人知道lxml(http://lxml.de/)中的解决方案吗?

其他没有使用xslt / lxml的解决方案?

哪一个最适合解决这个问题? (对于sed,只需要一行替换&#34; First Last&#34; with&#34; Something&#34;(假设输入xml文件中没有任何内容不会使sed无法正常工作。)是否有一个尊重xml规范的解决方案,但是只有一行代码?

2 个答案:

答案 0 :(得分:2)

在XSLT 3.0中,它非常接近您正在寻找的单行:

<xsl:transform version="3.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:mode on-no-match="shallow-copy"/>

  <xsl:template match="@*:userId[.='First Last']">
    <xsl:attribute name="{local-name()}" namespace="{namespace-uri()}">Something else</xsl:attribute>
  </xsl:template>

</xsl:transform>

答案 1 :(得分:1)

让我们从好消息开始吧。您可以使用替换属性的值 使用匹配的模板,无论名称空间如何,都使用特定名称 属性(@*)与谓词中的特定local-name()

下面给出的脚本包含2个此类模板,适用于providerIduserId

但坏消息是你不能完全“闭眼”命名空间 用过的。有关XSLT命名空间处理的规则要求使用XSLT 脚本必须包含所有使用的命名空间的定义。

请注意,下面的脚本包含这样的定义:xmlns:w15="urn:dummy_15",通常放在脚本的根标记中。

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform version="2.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:w15="urn:dummy_15">
  <xsl:output method="xml" encoding="UTF-8" indent="yes" />

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

  <xsl:template match="@*[local-name() = 'providerId']">
    <xsl:attribute name="{name()}">
      <xsl:value-of select="'Something else 1'"/>
    </xsl:attribute>
  </xsl:template>

  <xsl:template match="@*[local-name() = 'userId']">
    <xsl:attribute name="{name()}">
      <xsl:value-of select="'Something else 2'"/>
    </xsl:attribute>
  </xsl:template>
</xsl:transform>

有关工作示例,请参阅http://xsltransform.net/gVrtEmW

所以你可以拥有一个“样本”XSLT脚本,没有名称空间,但是在最后 那一刻,在实际运行脚本之前,你必须要看看 什么名称空间包含您的源XML文件并添加使用的规范 脚本的名称空间。