XSL在每个节点

时间:2016-06-29 11:46:31

标签: xslt xslt-1.0 xml-namespaces

我必须做一个XSL:

  • 几乎每个节点都重复命名空间声明< - 那就是我的问题,下一个应用程序(在其他地方)要求它
  • 更改默认名称空间URI (from here)
  • 将名称空间前缀从i更改为xsi
  • 更改根节点的名称
  • 为几个特定节点添加值
  • 向Root添加属性(processid =“1”)

输入:

      <oldRoot xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="old:namspace">
<Lists xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="old:namspace">
  <header xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="old:namspace">
    <createDate>2016-04-20</createDate>
  </header>
  <ListCode>1</ListCode>
    <ListLocalFlag xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="old:namspace" i:nil="true"/>
    <ListStatus>1</ListStatus>
    <addValueHere xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="old:namspace" i:nil="true"/> 
<dontTouchMe/>
</Lists>

期望的输出:

      <newRoot xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://new.namspace" processid="1">
<Lists xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://new.namspace">
  <header xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://new.namspace">
    <createDate>2016-04-20</createDate>
  </header>
  <ListCode>1</ListCode>
    <ListLocalFlag xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://new.namspace" i:nil="true"/>
    <ListStatus>1</ListStatus>
    <addValueHere xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://new.namspace">27</addValueHere>
<dontTouchMe/>
</Lists>

到目前为止我尝试了什么(没用,我尝试了很多方法):

    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
            xmlns="http://new.namspace"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            xmlns:i="DeleteMeLikeThisOrNeedCorrectURI?"
            xmlns:msxsl="urn:schemas-microsoft-com:xslt"
            xmlns:old="old:namspace"
            exclude-result-prefixes="i old msxsl">
<xsl:output omit-xml-declaration="no" indent="yes" method="xml"/>

<xsl:namespace-alias stylesheet-prefix="i" result-prefix="xsi"/>

<xsl:variable name="processid" select="1"/>
<xsl:variable name="nsmapdocString">
<root xml:space="preserve" xmlns="" >
  <namespace source="old:namspace" target="http://new.namspace"/>
</root>
</xsl:variable>
<xsl:param name="nsmapdoc" select="msxsl:node-set($nsmapdocString)" />

<xsl:template match="/" name="root">
<newRoot processid="{$processid}" xmlns:xsi="http://www.w3.or//2001/XMLSchema-instance" xmlns="http://new.namspace">
  <xsl:for-each select="node()|@*">
    <xsl:apply-templates/>
  </xsl:for-each>
</newRoot>
</xsl:template>

<xsl:template match="*[(local-name()='addValueHere' or local-name()='addSameValueHere2') and not(node())]" name="setValue">
<xsl:variable name="old-ns" select="namespace-uri()"/>
<xsl:variable name="map-entry" select="$nsmapdoc/root/namespace[@source=$old-ns]"/>
<xsl:variable name="new-ns">
  <xsl:choose>
    <xsl:when test="$map-entry">
      <xsl:value-of select="$map-entry/@target"/>
    </xsl:when>
    <xsl:otherwise>
      <xsl:value-of select="$old-ns"/>
    </xsl:otherwise>
  </xsl:choose>
</xsl:variable>
<xsl:element name="{local-name()}" namespace="{$new-ns}">
    <xsl:copy-of select="27" />      
  <!--<xsl:apply-templates/>-->
</xsl:element>
</xsl:template>

<xsl:template match="*[not((local-name()='addValueHere') and not(local-name()='addSameValueHere2')) and not(node())]" name="setRestNil">
<xsl:variable name="old-ns" select="namespace-uri()"/>
<xsl:variable name="map-entry" select="$nsmapdoc/root/namespace[@source=$old-ns]"/>
<xsl:variable name="new-ns">
  <xsl:choose>
    <xsl:when test="$map-entry">
      <xsl:value-of select="$map-entry/@target"/>
    </xsl:when>
    <xsl:otherwise>
      <xsl:value-of select="$old-ns"/>
    </xsl:otherwise>
  </xsl:choose>
</xsl:variable>
<xsl:element name="{local-name()}" namespace="{$new-ns}">     
  <xsl:attribute name="xsi:nil" namespace="http://www.w3.org/2001/XMLSchema-instance">
    <xsl:value-of select="true()"/>
  </xsl:attribute>
</xsl:element>
</xsl:template>
</xsl:stylesheet>

1 个答案:

答案 0 :(得分:2)

XSLT执行从一棵树到另一棵树的转换,然后序列化器开始生成结果树的表示为词法XML。标准的序列化程序将始终从树中删除冗余的命名空间,并且您无法在XSLT代码中执行任何操作来阻止这种情况;实现它的唯一方法是编写自己的序列化器。

难以满足这一要求的原因是这是一个不好的要求。没有合理的XML消费者应该要求它包含冗余的命名空间,因此永远不需要生成它们。