2013-04-08 100 views
0

我得到了一个XML,我转换成另一个XML,但在翻译之后,我得到了一些我想删除的具有空名称空间声明(xmlns="")的元素。删除元素中的空名称空间声明

其次我还想要在InterChangeHead元素中声明xmlns:xsi

输入XML

<?xml version="1.0" encoding="UTF-8"?> 
<PostenInterchange type="tag"> 
    <heInterchangeType>PostenInterchange</heInterchangeType> 
    <heVersion>1.4-rev3</heVersion> 
    <heTestindicator>1</heTestindicator> 
    <InterChangeHead type="tag"> 
     <heVersion>1</heVersion> 
     <heSenderid>SENDID</heSenderid> 
     <heRecipientid>RECIPID</heRecipientid> 
     <heXmlnsxsi>"http://www.w3.org/2001/XMLSchema-instance"</heXmlnsxsi> 
     <heXmlns>"posten.xsd"</heXmlns> 
     <Shipment type="tag"> 
      <heShipmenttype>IMP</heShipmenttype> 
      <Shipper type="tag"> 
       <name>Shipper</name> 
      </Shipper> 
      <Consignee type="tag"> 
       <name>Consignee</name> 
      </Consignee> 
      <GoodsData type="tag"> 
       <heSequencenumber>2</heSequencenumber> 
       <GrossWeight>0.000</GrossWeight> 
       <NetWeight>0.660</NetWeight> 
      </GoodsData> 
     </Shipment> 
    </InterChangeHead> 
</PostenInterchange> 

CURRENT XSLT

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" exclude-result-prefixes="xs fn"> 
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> 

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

    <!-- Copy local names --> 
    <xsl:template match="*"> 
     <xsl:element name="{name()}"> 
      <xsl:apply-templates select="@*|node()" /> 
     </xsl:element> 
    </xsl:template> 

    <!-- Rename elements beginning with "he" to elements without the "he" --> 
    <xsl:template match="node()"> 
     <xsl:choose> 
      <xsl:when test="substring(local-name(), 1, 2) = 'he'"> 
       <xsl:element name="{substring(local-name(), 3)}"> 
        <xsl:apply-templates select="@*|node()" /> 
       </xsl:element> 
      </xsl:when> 
      <xsl:otherwise> 
       <xsl:copy> 
        <xsl:apply-templates select="@*|node()" /> 
       </xsl:copy> 
      </xsl:otherwise> 
     </xsl:choose> 
    </xsl:template> 

    <!-- Correct InterChangeHead element --> 
    <xsl:template match="InterChangeHead"> 
     <xsl:element name="InterChangeHead" namespace="posten.xsd">  
      <!-- Copy childs --> 
      <xsl:apply-templates select="child::node()" /> 
     </xsl:element> 
    </xsl:template> 

    <!-- Remove type attribute --> 
    <xsl:template match="@type"/> 

    <!-- Remove unnecessary elements --> 
    <xsl:template match="heXmlnsxsi" /> 
    <xsl:template match="heXmlns" /> 
</xsl:stylesheet> 

电流输出

<?xml version="1.0" encoding="UTF-8"?> 
<PostenInterchange> 
    <InterchangeType>PostenInterchange</InterchangeType> 
    <Version>1.4-rev3</Version> 
    <Testindicator>1</Testindicator> 
    <InterChangeHead xmlns="posten.xsd"> 
     <Version xmlns="">1</Version> 
     <Senderid xmlns="">SENDID</Senderid> 
     <Recipientid xmlns="">RECIPID</Recipientid> 
     <Shipment xmlns=""> 
      <Shipmenttype>IMP</Shipmenttype> 
      <Shipper> 
       <name>Shipper</name> 
      </Shipper> 
      <Consignee> 
       <name>Consignee</name> 
      </Consignee> 
      <GoodsData> 
       <Sequencenumber>2</Sequencenumber> 
       <GrossWeight>0.000</GrossWeight> 
       <NetWeight>0.660</NetWeight> 
      </GoodsData> 
     </Shipment> 
    </InterChangeHead> 
</PostenInterchange> 

所需的输出

<?xml version="1.0" encoding="UTF-8"?> 
<PostenInterchange> 
    <InterchangeType>PostenInterchange</InterchangeType> 
    <Version>1.4-rev3</Version> 
    <Testindicator>1</Testindicator> 
    <InterChangeHead xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="posten.xsd" > 
     <Version>1</Version> 
     <Senderid>SENDID</Senderid> 
     <Recipientid>RECIPID</Recipientid> 
     <Shipment> 
      <Shipmenttype>IMP</Shipmenttype> 
      <Shipper> 
       <name>Shipper</name> 
      </Shipper> 
      <Consignee> 
       <name>Consignee</name> 
      </Consignee> 
      <GoodsData> 
       <Sequencenumber>2</Sequencenumber> 
       <GrossWeight>0.000</GrossWeight> 
       <NetWeight>0.660</NetWeight> 
      </GoodsData> 
     </Shipment> 
    </InterChangeHead> 
</PostenInterchange> 

谁能帮助我的最后一位?我加了一个模板,因为我认为这将删除空的命名空间声明:

<!-- Copy local names --> 
<xsl:template match="*"> 
    <xsl:element name="{name()}"> 
     <xsl:apply-templates select="@*|node()" /> 
    </xsl:element> 
</xsl:template> 

回答

1

请记住,xmlns="..."声明为其所连接的元素及其所有后代设置默认名称空间,除非由树下方的另一个xmlns="..."进行反转。因此,在您希望的输出中,<InterChangeHead xmlns="posten.xsd" >下的所有后代元素也位于posten.xsd名称空间中,并且您的模板需要反映此情况。由于您使用XSLT 2.0,你可以使用条件的XPath表达式的一部分,这样做很容易:

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

    <!-- Copy elements, fixing up names and namespaces as required --> 
    <xsl:template match="*"> 
     <xsl:element name="{if(substring(local-name(), 1, 2) = 'he') 
          then substring(local-name(), 3) else local-name()}" 
        namespace="{if(ancestor-or-self::InterChangeHead) 
           then 'posten.xsd' else ''}"> 
      <xsl:apply-templates select="@*|node()" /> 
     </xsl:element> 
    </xsl:template> 

    <!-- specific template for InterChangeHead to add the (unused) xsi 
     namespace declaration --> 
    <xsl:template match="InterChangeHead"> 
     <InterChangeHead xmlns="posten.xsd" 
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
     <xsl:apply-templates select="@*|node()" /> 
     </InterChangeHead> 
    </xsl:template> 

    <xsl:template match="@* | text()"> 
     <xsl:copy-of select="." /> 
    </xsl:template> 

    <!-- Remove type attribute --> 
    <xsl:template match="@type"/> 

    <!-- Remove unnecessary elements --> 
    <xsl:template match="heXmlnsxsi" /> 
    <xsl:template match="heXmlns" /> 
</xsl:stylesheet> 

我添加了一个特定的模板声明对InterChangeHeadxsi命名空间,虽然我不知道为什么有必要包含该声明,因为它在输出XML文档中的任何地方都不使用。如果事实证明没有必要,您可以简单地删除<xsl:template match="InterChangeHead">,因为匹配*的模板也将处理InterChangeHead,正确设置名称空间。

+0

为什么template''需要? – 2013-04-08 11:58:22

+0

@MarkVeenstra我从技术上来说并不是因为你正在处理的XML输入没有任何属性(除了你无视的'标签'之外)以及该模板在'text()节点与默认相同。习惯,我认为,我总是倾向于从身份模板开始...... – 2013-04-08 12:01:55

0

您需要更改每个元素节点的命名空间,所以更改模板

<!-- Correct InterChangeHead element --> 
<xsl:template match="InterChangeHead"> 
    <xsl:element name="InterChangeHead" namespace="posten.xsd">  
     <!-- Copy childs --> 
     <xsl:apply-templates select="child::node()" /> 
    </xsl:element> 
</xsl:template> 

<!-- Correct InterChangeHead element and descendants --> 
<xsl:template match="InterChangeHead | InterChangeHead//*"> 
    <xsl:element name="{local-name()}" namespace="posten.xsd">  
     <!-- Copy childs --> 
     <xsl:apply-templates select="@* | node()" /> 
    </xsl:element> 
</xsl:template> 

下面是一个简化代码的完整样式表:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" exclude-result-prefixes="xs fn"> 
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> 

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

    <!-- Correct InterChangeHead element --> 
    <xsl:template match="InterChangeHead | InterChangeHead//*"> 
     <xsl:element name="{local-name()}" namespace="posten.xsd">  
      <!-- Copy childs --> 
      <xsl:apply-templates select="@* | node()" /> 
     </xsl:element> 
    </xsl:template> 

    <!-- Rename elements beginning with "he" to elements without the "he" --> 
    <xsl:template match="InterChangeHead//*[substring(local-name(), 1, 2) = 'he']" priority="5"> 
       <xsl:element name="{substring(local-name(), 3)}" namespace="posten.xsd"> 
        <xsl:apply-templates select="@*|node()" /> 
       </xsl:element> 
    </xsl:template> 

    <!-- Remove type attribute --> 
    <xsl:template match="@type"/> 

    <!-- Remove unnecessary elements --> 
    <xsl:template match="heXmlnsxsi" priority="6"/> 
    <xsl:template match="heXmlns" priority="6"/> 
</xsl:stylesheet>