XSLT动态命名空间元素生成

时间:2016-06-16 05:33:36

标签: xml xslt namespaces

我有以下输入为XML:

<?xml version="1.0" encoding="UTF-8"?>
<Header xmlns="http://www.oracle.com/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.oracle.com/webfolder/1/ http://www.oracle.com/webfolder/1/aXML.xsd" creator="mine">
   <SubHead1 values="1">
      <CoverPage>
         <Number>324</Number>
         <Status>test</Status>
         <ChangeType>test</ChangeType>
         <DescriptionOfChange>test</DescriptionOfChange>
         <ReasonForChange>test</ReasonForChange>
         <ReasonCode>test</ReasonCode>
         <Workflow>test</Workflow>
      </CoverPage>
      <PageTwo>
         <single1>No</single1>
         <single2>No</single2>
         <multisingle2>
            <Value>r</Value>
            <Value>i</Value>
            <Value>h</Value>
            <Value>m</Value>
         </multisingle2>
         <CreateUser>mine</CreateUser>
         <Date01>2016-04-08T18:30:58Z</Date01>
      </PageTwo>
   </SubHead1>
   <SubHead2 values="2">
      <TitleBlock>
         <Number>22</Number>
         <PartType>Part</PartType>
         <LifecyclePhase>Preliminary</LifecyclePhase>
         <Description>TEST</Description>
         <Rev>88</Rev>
      </TitleBlock>
      <PageTwo>
         <single1>z</single1>
         <single2>a</single2>
         <multisingle1>
            <Value>b</Value>
            <Value>c</Value>
            <Value>d</Value>
         </multisingle1>
         <multisingle2>
            <Value>7</Value>
            <Value>ac</Value>
         </multisingle2>
         <single3>f</single3>
         <CreateUser>mine</CreateUser>
         <Date01>2016-04-27T17:31:44Z</Date01>
      </PageTwo>
   </SubHead2>
</Header>

使用以下XSLT,我能够生成输出:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.oracle.com/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0" xsi:schemaLocation="http://www.oracle.com/webfolder/1/ http://www.oracle.com/webfolder/1/aXML.xsd">
   <xsl:output method="xml" indent="yes" />
   <xsl:strip-space elements="*" />
   <xsl:template match="/*">
      <Header>
         <SubHead2>
            <xsl:attribute name="values">
               <xsl:value-of select="/*/*[2]/@values" />
            </xsl:attribute>
            <xsl:apply-templates select="/*/*[2]/*[1]/*" />
            <xsl:for-each select="/*/*[2]/*[2]/*">
               <xsl:variable name="j" select="position()" />
               <xsl:if test="/*/*[2]/*[2]/*[$j] and not(/*/*[2]/*[2]/*[$j]/*)">
                  <xsl:copy-of select="/*/*[2]/*[2]/*[$j]" />
               </xsl:if>
               <xsl:for-each select="/*/*[2]/*[2]/*/*">
                  <xsl:variable name="i" select="position()" />
                  <xsl:if test="$i = 1">
                     <xsl:apply-templates select="/*/*[2]/*/*[$j][*[2]]">
                        <xsl:with-param name="testParam3" select="$i" />
                     </xsl:apply-templates>
                  </xsl:if>
               </xsl:for-each>
            </xsl:for-each>
            <SubHead1>
               <xsl:apply-templates select="/*/*[1]/*[1]/*" />
            </SubHead1>
         </SubHead2>
         <xsl:for-each select="/*/*[2]/*[2]/*">
            <xsl:variable name="j" select="position()" />
            <xsl:for-each select="*">
               <xsl:variable name="i" select="position()" />
               <xsl:if test="$i &gt; 1">
                  <xsl:call-template name="attr">
                     <xsl:with-param name="testParam1" select="$j" />
                     <xsl:with-param name="testParam2" select="$i" />
                  </xsl:call-template>
               </xsl:if>
            </xsl:for-each>
         </xsl:for-each>
      </Header>
   </xsl:template>
   <xsl:template match="/*/*[2]/*/*[*[2]]">
      <xsl:copy>
         <xsl:copy-of select="@* | *[1]" />
      </xsl:copy>
   </xsl:template>
   <xsl:template match="*">
      <xsl:copy-of select="." />
   </xsl:template>
   <xsl:template match="/*/*[2]/*/*[*[2]]">
      <xsl:param name="testParam3" />
      <xsl:copy>
         <xsl:copy-of select="@* | *[$testParam3]" />
      </xsl:copy>
   </xsl:template>
   <xsl:template name="attr">
      <xsl:param name="testParam1" />
      <xsl:param name="testParam2" />
      <SubHead2>
         <xsl:attribute name="uniqueId">
            <xsl:value-of select="/*/*[2]/@values" />
         </xsl:attribute>
         <Number>
            <xsl:value-of select="/*/*[2]/*[1]/*[1]" />
         </Number>
         <xsl:apply-templates select="/*/*[2]/*/*[$testParam1][*[2]]">
            <xsl:with-param name="testParam3" select="$testParam2" />
         </xsl:apply-templates>
      </SubHead2>
   </xsl:template>
</xsl:stylesheet>

输出(XML):

<?xml version="1.0" encoding="UTF-8"?>
<Header xmlns="http://www.oracle.com/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <SubHead2 values="2">
        <Number>22</Number>
        <PartType>Part</PartType>
        <LifecyclePhase>Preliminary</LifecyclePhase>
        <Description>TEST</Description>
        <Rev>88</Rev>
        <single1>z</single1>
        <single2>a</single2>
        <multisingle1>
            <Value>b</Value>
        </multisingle1>
        <multisingle2>
            <Value>7</Value>
        </multisingle2>
        <single3>f</single3>
        <CreateUser>mine</CreateUser>
        <Date01>2016-04-27T17:31:44Z</Date01>
        <SubHead1>
            <Number>324</Number>
            <Status>test</Status>
            <ChangeType>test</ChangeType>
            <DescriptionOfChange>test</DescriptionOfChange>
            <ReasonForChange>test</ReasonForChange>
            <ReasonCode>test</ReasonCode>
            <Workflow>test</Workflow>
        </SubHead1>
    </SubHead2>
    <SubHead2 uniqueId="2">
        <Number>22</Number>
        <multisingle1>
            <Value>c</Value>
        </multisingle1>
    </SubHead2>
    <SubHead2 uniqueId="2">
        <Number>22</Number>
        <multisingle1>
            <Value>d</Value>
        </multisingle1>
    </SubHead2>
    <SubHead2 uniqueId="2">
        <Number>22</Number>
        <multisingle2>
            <Value>ac</Value>
        </multisingle2>
    </SubHead2>
</Header>

在输出中,您可以看到我无法在“标题”元素中包含“creator”属性

问题是我无法控制传入的XML,因为命名空间值可以与新属性一起动态生成

例如:(动态根元素)

<Header xmlns="http://www.oracle.com/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xsi:schemaLocation="http://www.oracle.com/webfolder/1/ http://www.oracle.com/webfolder/1/aXML.xsd" foo="bar">
<Header xmlns="http://www.ex.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xsi:schemaLocation="http://www.sample.com/ex/ http://www.sample.com/ex/foo.xsd">

我想使用Root节点生成与输入XML

相同的输出

任何帮助都会有用

由于

1 个答案:

答案 0 :(得分:0)

如果你真的想要处理带有不同命名空间的XML文档,你可以做的是首先定义一个变量来存储传入文档的命名空间uri(这假设XML文档只有命名空间)

<xsl:variable name="namespace" select="namespace-uri(/*)" />

然后使用<Header>并指定命名空间而不是xsl:element来创建元素

<xsl:element name="Header" namespace="{$namespace}">

您必须为您创建的每个静态元素执行此操作

试试这个简化的XML作为例子

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.oracle.com/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0" xsi:schemaLocation="http://www.oracle.com/webfolder/1/ http://www.oracle.com/webfolder/1/aXML.xsd">
   <xsl:output method="xml" indent="yes" />
   <xsl:strip-space elements="*" />
   <xsl:variable name="namespace" select="namespace-uri(/*)" />

    <xsl:template match="/*">
      <xsl:element name="Header" namespace="{$namespace}">
         <xsl:copy-of select="namespace::*" />
         <xsl:copy-of select="@*" />
         <xsl:element name="SubHead2" namespace="{$namespace}">
            <xsl:attribute name="values">
               <xsl:value-of select="/*/*[2]/@values" />
            </xsl:attribute>
         </xsl:element>
      </xsl:element>
   </xsl:template>

</xsl:stylesheet>