任务是删除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,但我认为这也归结为正则表达式。
编辑:我已经从xsl remove all non-numeric characters and leading 1尝试了以下XSLT:
<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>
但这并没有成功。
答案 0 :(得分:2)
我引用你自己的回答:
正如你已经提到的,它只需要形成良好的形状,所以 “伪造的”命名空间声明解决了。我必须使用1.0版本 我的xsltproc似乎只支持该版本:
不是,看看here。您是否看到要删除的任何非数字字符?
实际上,情况恰恰相反。 前缀是任意的,并且是唯一标识命名空间的完整命名空间声明。换句话说,元素
<ns2:CustomerIdentity>
其中xmlns:ns2 =“swissdec.ch/schema/sd/20130514/SalaryDeclaration”
和
<ns2:CustomerIdentity>
其中xmlns:ns2 =“www.testing.com”
就XML解析器而言,是不同的元素。另一方面,
<ns2:CustomerIdentity>
其中xmlns:ns2 =“swissdec.ch/schema/sd/20130514/SalaryDeclaration”
和
<other:CustomerIdentity>
其中xmlns:other =“swissdec.ch/schema/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>
答案 1 :(得分:1)
您可以使用XSLT 2.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>
答案 2 :(得分:0)
就像我编辑自己的问题一样,我看到了一种方式(也感谢xsl remove all non-numeric characters and leading 1)。正如您已经提到的那样,它只需要格式正确,因此“伪造”的命名空间声明可以解决。我必须使用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>
感谢您引导我走向正确的方向!