使用XSLT清除XML文件中的节点值

时间:2012-02-27 21:40:13

标签: xml xslt

我有以下XML文档

    <?mso-infoPathSolution name="urn:schemas-microsoft-com:office:infopath:TCM-TCP:-myXSD-2012-02-20T14-33-22" solutionVersion="1.0.0.65" productVersion="14.0.0.0" PIVersion="1.0.0.0" href="https://devcoop.oceanspray.com/sites/TCM2/FormServerTemplates/TCM-TCP.xsn"?>
<?mso-application progid="InfoPath.Document" versionProgid="InfoPath.Document.3"?>
<my:myFields xml:lang="en-US" xmlns:my="http://schemas.microsoft.com/office/infopath/2003/myXSD/2012-02-20T14:33:22" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:xd="http://schemas.microsoft.com/office/infopath/2003">
  <my:Header>
    <my:ProjectName>Something</my:ProjectName>
    <my:ProjectCreationDate>2/21/2012 12:00 AM</my:ProjectCreationDate>
  </my:Header>
  <my:Details>
    <my:DescriptionOfProposal>
      Will be filled in when saved<html xml:space="preserve" xmlns="http://www.w3.org/1999/xhtml"><p>testestdsgsgasfgf a<strong>asdf </strong>adf asdf asdf as</p></html>
    </my:DescriptionOfProposal>
    <my:PurposeOfChange>Will be filled in when saved</my:PurposeOfChange>
  </my:Details>
</my:myFields>

我想在此文档上运行一个XSLT文件,该文件将清除my:DescriptionOfPropsal节点的值。它将完全清除文本和子节点。我有以下XSLT样式表

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:my="urn:schemas-microsoft-com:office:infopath:TCM-TCP:-myXSD-2012-02-20T14-33-22"
                xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
  <xsl:output method="xml" indent="yes"/>

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

  <xsl:template match="//my:DescriptionOfProposal">
    <my:DescriptionOfProposal>
    </my:DescriptionOfProposal>
  </xsl:template>


</xsl:stylesheet>

但这似乎不起作用。我用它做了一堆测试,我相信它与节点上的命名空间有关,因为我可以对另一个没有命名空间的简单文档进行相同类型的转换,我可以让它工作。

3 个答案:

答案 0 :(得分:1)

这很明显 - 您使用的名称空间不正确

提供的XML文档中的my:DescriptionOfProposal节点属于命名空间:

"http://schemas.microsoft.com/office/infopath/2003/myXSD/2012-02-20T14:33:22"

但是,在您的XSLT代码中,您将"my:"前缀与不同的命名空间相关联:

"urn:schemas-microsoft-com:office:infopath:TCM-TCP:-myXSD-2012-02-20T14-33-22"

<强>解决方案

更正转换中的命名空间。

<强>替换

xmlns:my="urn:schemas-microsoft-com:office:infopath:TCM-TCP:-myXSD-2012-02-20T14-33-22"

<强>与

xmlns:my="http://schemas.microsoft.com/office/infopath/2003/myXSD/2012-02-20T14:33:22"

通过此更改以及重写模板的轻微重构,您的转换将变为:

<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:my="http://schemas.microsoft.com/office/infopath/2003/myXSD/2012-02-20T14:33:22"
  xmlns:msxsl="urn:schemas-microsoft-com:xslt"
  exclude-result-prefixes="msxsl">
    <xsl:output method="xml" indent="yes"/>
    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="my:DescriptionOfProposal/node()"/>
</xsl:stylesheet>

以及何时应用于提供的XML文档

<?mso-infoPathSolution name="urn:schemas-microsoft-com:office:infopath:TCM-TCP:-myXSD-2012-02-20T14-33-22" solutionVersion="1.0.0.65" productVersion="14.0.0.0" PIVersion="1.0.0.0" href="https://devcoop.oceanspray.com/sites/TCM2/FormServerTemplates/TCM-TCP.xsn"?>
<?mso-application progid="InfoPath.Document" versionProgid="InfoPath.Document.3"?>
<my:myFields xml:lang="en-US" xmlns:my="http://schemas.microsoft.com/office/infopath/2003/myXSD/2012-02-20T14:33:22" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:xd="http://schemas.microsoft.com/office/infopath/2003">
    <my:Header>
        <my:ProjectName>Something</my:ProjectName>
        <my:ProjectCreationDate>2/21/2012 12:00 AM</my:ProjectCreationDate>
    </my:Header>
    <my:Details>
        <my:DescriptionOfProposal>       Will be filled in when saved
            <html xml:space="preserve" xmlns="http://www.w3.org/1999/xhtml">
                <p>testestdsgsgasfgf a
                    <strong>asdf </strong>adf asdf asdf as
                </p>
            </html>
        </my:DescriptionOfProposal>
        <my:PurposeOfChange>Will be filled in when saved</my:PurposeOfChange>
    </my:Details>
</my:myFields>

产生了想要的正确结果

<?xml version="1.0" encoding="UTF-16"?>
<?mso-infoPathSolution name="urn:schemas-microsoft-com:office:infopath:TCM-TCP:-myXSD-2012-02-20T14-33-22" solutionVersion="1.0.0.65" productVersion="14.0.0.0" PIVersion="1.0.0.0" href="https://devcoop.oceanspray.com/sites/TCM2/FormServerTemplates/TCM-TCP.xsn"?>
<?mso-application progid="InfoPath.Document" versionProgid="InfoPath.Document.3"?>
<my:myFields xml:lang="en-US" xmlns:my="http://schemas.microsoft.com/office/infopath/2003/myXSD/2012-02-20T14:33:22" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:xd="http://schemas.microsoft.com/office/infopath/2003">
    <my:Header>
        <my:ProjectName>Something</my:ProjectName>
        <my:ProjectCreationDate>2/21/2012 12:00 AM</my:ProjectCreationDate>
    </my:Header>
    <my:Details>
        <my:DescriptionOfProposal></my:DescriptionOfProposal>
        <my:PurposeOfChange>Will be filled in when saved</my:PurposeOfChange>
    </my:Details>
</my:myFields>

答案 1 :(得分:1)

正如其他人都诊断出名称空间问题并找到了修复程序一样,请参阅答案以更正您的代码。不过,我想建议你不要纠正那些命名空间。使用contains() function ..我知道在这种情况下它没有用,只是为了分享我正在编写解决方案的知识:)

<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:msxsl="urn:schemas-microsoft-com:xslt"
  exclude-result-prefixes="msxsl">
  <xsl:output method="xml" indent="yes"/>
  <xsl:template match="@* | node()">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="node()[contains(name(),'DescriptionOfProposal')]">
    <xsl:copy/>
  </xsl:template>
</xsl:stylesheet>

以上代码从不关心您在XML文件中使用的命名空间:)

这是另一种选择..

<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:msxsl="urn:schemas-microsoft-com:xslt"
  exclude-result-prefixes="msxsl">
  <xsl:output method="xml" indent="yes"/>
  <xsl:template match="@* | node()">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="node()[parent:: node()[contains(name(),'DescriptionOfProposal')]]"/>
</xsl:stylesheet>

你可以使用其中任何一个:) 编辑:第二种方法是最不喜欢的,因为反向轴:)
根据Dimitre的建议添加了这种方法......

<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:msxsl="urn:schemas-microsoft-com:xslt"
  exclude-result-prefixes="msxsl">
  <xsl:output method="xml" indent="yes"/>
  <xsl:template match="@* | node()">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="node()[local-name() = 'DescriptionOfProposal']">
    <xsl:copy/>
  </xsl:template>
</xsl:stylesheet>

答案 2 :(得分:0)

绑定到my的命名空间在XML和XSLT中是不同的:

XML:

xmlns:my="http://schemas.microsoft.com/office/infopath/2003/myXSD/2012-02-20T14:33:22"

XSLT:

xmlns:my="urn:schemas-microsoft-com:office:infopath:TCM-TCP:-myXSD-2012-02-20T14-33-22"

更改XSLT中的命名空间或添加新命名空间。 E.g:

xmlns:my2="http://schemas.microsoft.com/office/infopath/2003/myXSD/2012-02-20T14:33:22"

然后在你的模板中:

<xsl:template match="my2:DescriptionOfProposal">
    <my2:DescriptionOfProposal/>
</xsl:template>

请注意,//完全没必要。