更改特定XML标记中的文本(去掉非数字字符)



任务是清除XML文件中以下CustomerIdentity元素中的任何非数字字符:

<ns2:TaxAtSource institutionID="#SG">
    <ns2:CantonID>SG</ns2:CantonID>
    <ns2:CustomerIdentity>CHE123.456 </ns2:CustomerIdentity>
</ns2:TaxAtSource>

我尝试了sed(它会很优雅,但由于非数字字符可以在CustomerIdentity标记之间的任何位置,所以正则表达式有点麻烦)。我也尝试过XSLT,但是名称空间ns2在识别标记(非引用名称空间)时遇到了麻烦。因此,如果有人有一个有效的解决方案来处理XML文件,则如下所示(其余部分应该保持不变):

<ns2:TaxAtSource institutionID="#SG">
    <ns2:CantonID>SG</ns2:CantonID>
    <ns2:CustomerIdentity>123456</ns2:CustomerIdentity>
</ns2:TaxAtSource>

我们将不胜感激。一位同事建议使用AWK或ruby,但我认为这也可以归结为regex。

编辑:我已经从xsl中尝试了以下XSLT,删除了所有非数字字符和前导1:

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="text"/>
<xsl:template match="text()">
    <xsl:variable name="vnumsOnly" select=
    "translate(., translate(.,'0123456789',''), '')
    "/>
    <xsl:value-of select=
    "substring($vnumsOnly, (substring($vnumsOnly,1,1)='1') +1)"/>
</xsl:template>
</xsl:stylesheet>

但这并没有完全奏效。

我引用你自己的答案:

正如你已经提到的,它只需要良好地形成,所以"faked"命名空间声明成功。我必须使用1.0版本,因为我的xsltproc似乎只支持那个版本:

不是,看看这里。你看到任何非数字字符被删除了吗?


事实上,恰恰相反。是任意的前缀和唯一标识命名空间的完整命名空间声明。换句话说,元素

<ns2:CustomerIdentity> 

其中xmlns:ns2="swissdec.ch/schema/sd/20130514/SalaryDeclaration"

<ns2:CustomerIdentity> 

其中xmlns:ns2="www.testing.com"

不同的元素。另一方面,

<ns2:CustomerIdentity> 

其中xmlns:ns2="swissdec.ch/schema/sd/20130514/SalaryDeclaration"

<other:CustomerIdentity> 

其中xmlns:other="swissdec.ch/schem/sd/2013051/SalaryDeclaration"

识别相同的元素。因此,当您转换XML文档并需要访问单个元素时,您需要声明与源文档中完全相同的名称空间,但您可以为其选择另一个前缀。

样式表

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
  version="1.0"
  xmlns:ns2="swissdec.ch/schema/sd/20130514/SalaryDeclaration">
    <xsl:output method="xml"  encoding="UTF-8" indent="yes" />
    <xsl:strip-space elements="*"/>
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="ns2:CustomerIdentity/text()">
        <xsl:value-of 
          select="translate(., translate(.,'0123456789',''), '')"/>
    </xsl:template>
</xsl:transform>

XML输入

<ns2:TaxAtSource institutionID="#SG" 
  xmlns:ns2="swissdec.ch/schema/sd/20130514/SalaryDeclaration">
    <ns2:CantonID>SG</ns2:CantonID>
    <ns2:CustomerIdentity>CHE123.456 </ns2:CustomerIdentity>
</ns2:TaxAtSource>

XML输出

<?xml version="1.0" encoding="UTF-8"?>
<ns2:TaxAtSource 
  xmlns:ns2="swissdec.ch/schema/sd/20130514/SalaryDeclaration" 
  institutionID="#SG">
   <ns2:CantonID>SG</ns2:CantonID>
   <ns2:CustomerIdentity>123456</ns2:CustomerIdentity>
</ns2:TaxAtSource>

您可以使用XSLT2.0的替换功能;

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"
xmlns:ns2="www.testing.com"
exclude-result-prefixes="ns2">
    <xsl:output method="xml" indent="yes" />
    <xsl:template match="ns2:CustomerIdentity">
        <ns2:CustomerIdentity>
            <xsl:value-of select='replace(., "[a-zA-Z. ]+","")'/>
        </ns2:CustomerIdentity>
    </xsl:template>
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

正如我编辑自己的问题一样,我看到了一种方法(也多亏了xsl删除了所有非数字字符和前导1)。正如您已经提到的,它只需要格式良好,所以"faked"命名空间声明就可以了。我必须使用1.0版本,因为我的xsltproc似乎只支持这个版本:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
xmlns:ns2="www.testing.com" exclude-result-prefixes="ns2">
    <xsl:output method="xml" indent="yes" />
    <xsl:template match="text()">
        <xsl:variable name="vnumsOnly" select=
        "translate(., translate(.,'0123456789',''), '')
        "/>
        <xsl:value-of select=
        "substring($vnumsOnly, (substring($vnumsOnly,1,1)='1') +1)"/>
    </xsl:template>
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

谢谢你把我引导到正确的方向!

相关内容

  • 没有找到相关文章

最新更新