2

如果我有这个输入文件:

<root> 
    <node id="N1">
        <fruit id="small_fruit">
            <orange id="1" action="create">
                <attribute>
                    <color>yellow</color>
                </attribute>
            </orange>
        </fruit>

        <fruit id="large_fruit" action="create">
            <melon id="1" action="destroy">
                <attribute>
                    <color>green</color>
                </attribute>
            </melon>
        </fruit>            
    </node>

    <node id="N2">
        <dog id="small_dog">    
            <poodle id="1" action="create">
                <attribute>
                    <color>Yellow</color>    
                </attribute>
            </poodle>       

            <poodle id="1" action="change">
                <attribute>
                    <color>Brown</color>        
                </attribute>
            </poodle>

            <terrier id="2" action="destroy">
                <attribute>
                    <color>Blue</color>    
                </attribute>
            </terrier>
        </dog>                          
    </node>
</root>

我需要分成两个文件: output1: node_destroy.xml

<root> 
    <node id="N1">          
        <fruit id="large_fruit" action="create">
            <melon id="1" action="destroy">
                <attribute>
                    <color>green</color>
                </attribute>
            </melon>
        </fruit>            
    </node>

    <node id="N2">
        <dog id="small_dog">                
            <terrier id="2" action="destroy">
                <attribute>
                    <color>Blue</color>    
                </attribute>
            </terrier>
        </dog>                          
    </node>
</root>

输出2:node_other_than_destroy.xml

<root> 
    <node id="N1">
        <fruit id="small_fruit">
            <orange id="1" action="create">
                <attribute>
                    <color>yellow</color>
                </attribute>
            </orange>
        </fruit>                  
    </node>

    <node id="N2">
        <dog id="small_dog">    
            <poodle id="1" action="create">
                <attribute>
                    <color>Yellow</color>    
                </attribute>
            </poodle>       

            <poodle id="1" action="change">
                <attribute>
                    <color>Brown</color>        
                </attribute>
            </poodle>
        </dog>                          
    </node>
</root>

基本上,我需要将带有 action='destroy' 的节点删除到一个文件中,而将其他带有其他操作的节点删除到另一个文件中。(选中的动作节点是甜瓜、贵宾犬、梗犬而不是它们的父母,即水果和狗

请帮我处理转换文件。非常感谢。

问候,约翰

4

2 回答 2

2

您使用哪种 XSLT 处理器?如果那是像 Saxon 9 或 AltovaXML 或 XmlPrime 这样的 XSLT 2.0 处理器,那么您可以使用xsl:result-document instruction. 对于 XSLT 1.0 处理器,您需要检查处理器是否支持扩展指令来创建多个结果文档。因此,请告诉我们您使用哪种处理器,然后我们可以为您的输入样本和所需的输出样本建议具体的代码样本。

[编辑] 我准备了一个 XSLT 2.0 示例:

<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  exclude-result-prefixes="xs"
  version="2.0">

  <xsl:param name="action" as="xs:string" select="'destroy'"/>

  <xsl:strip-space elements="*"/>
  <xsl:output indent="yes"/>

  <xsl:template match="/">
    <xsl:result-document href="node_{$action}.xml">
      <xsl:apply-templates/>
    </xsl:result-document>
    <xsl:result-document href="node_other_than_{$action}.xml">
      <xsl:apply-templates mode="other"/>
    </xsl:result-document>
  </xsl:template>

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

  <xsl:template match="/*/*[*/*[@action = $action]] 
                       | /*/*/*[*[@action = $action]]">
    <xsl:next-match/>
  </xsl:template>

  <xsl:template match="/*/*[not(*/*[@action = $action])] 
                       | /*/*/*[not(*[@action = $action])]
                       | /*/*/*/*[not(@action = $action)]"/>

  <xsl:template match="/*/*[*/*[not(@action = $action)]] 
                       | /*/*/*[*[not(@action = $action)]]" mode="other">
    <xsl:next-match/>
  </xsl:template>

  <xsl:template match="/*/*[not(*/*[not(@action = $action)])] 
                       | /*/*/*[not(*[not(@action = $action)])]
                       | /*/*/*/*[@action = $action]" mode="other"/>


</xsl:stylesheet>
于 2012-05-06T10:15:48.747 回答
2

在 XSLT 1.0 中,没有一种方法可以从一次转换的执行中创建多个输出

下面是两个单独的 XSLT 1.0 转换

第一个只产生结果action="destroy

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

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

 <xsl:template match="node[not(*/*/@action = 'destroy')]"/>
 <xsl:template match="node/*[not(*/@action = 'destroy')]"/>

 <xsl:template match="node/*/*[not(@action = 'destroy')]"/>
</xsl:stylesheet>

当此转换应用于提供的 XML 文档时

<root>
    <node id="N1">
        <fruit id="small_fruit">
            <orange id="1" action="create">
                <attribute>
                    <color>yellow</color>
                </attribute>
            </orange>
        </fruit>

        <fruit id="large_fruit" action="create">
            <melon id="1" action="destroy">
                <attribute>
                    <color>green</color>
                </attribute>
            </melon>
        </fruit>
    </node>

    <node id="N2">
        <dog id="small_dog">
            <poodle id="1" action="create">
                <attribute>
                    <color>Yellow</color>
                </attribute>
            </poodle>

            <poodle id="1" action="change">
                <attribute>
                    <color>Brown</color>
                </attribute>
            </poodle>

            <terrier id="2" action="destroy">
                <attribute>
                    <color>Blue</color>
                </attribute>
            </terrier>
        </dog>
    </node>
</root>

产生了想要的正确结果:

<root>
   <node id="N1">
      <fruit id="large_fruit" action="create">
         <melon id="1" action="destroy">
            <attribute>
               <color>green</color>
            </attribute>
         </melon>
      </fruit>
   </node>
   <node id="N2">
      <dog id="small_dog">
         <terrier id="2" action="destroy">
            <attribute>
               <color>Blue</color>
            </attribute>
         </terrier>
      </dog>
   </node>
</root>

第二个转换产生所有“非破坏”内容:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

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

 <xsl:template match="node[not(*/*/@action[not(. = 'destroy')])]"/>
 <xsl:template match="node/*[not(*/@action[not(. = 'destroy')])]"/>

 <xsl:template match="node/*/*[@action = 'destroy']"/>
</xsl:stylesheet>

当此转换应用于同一个 XML 文档(如上)时,会产生所需的结果:

<root>
   <node id="N1">
      <fruit id="small_fruit">
         <orange id="1" action="create">
            <attribute>
               <color>yellow</color>
            </attribute>
         </orange>
      </fruit>
   </node>
   <node id="N2">
      <dog id="small_dog">
         <poodle id="1" action="create">
            <attribute>
               <color>Yellow</color>
            </attribute>
         </poodle>
         <poodle id="1" action="change">
            <attribute>
               <color>Brown</color>
            </attribute>
         </poodle>
      </dog>
   </node>
</root>

二、XSLT 2.0 解决方案——在同一个转换中创建两个输出文件:

<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>

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

 <xsl:template match="/">
   <xsl:variable name="vResultDestroyed">
     <xsl:apply-templates mode="destroyed"/>
   </xsl:variable>
   <xsl:variable name="vResultNonDestroyed">
     <xsl:apply-templates mode="non-destroyed"/>
   </xsl:variable>

   <xsl:for-each select="1 to 2">
     <xsl:result-document
        href="file:///c:temp/delete/{'non-'[position()=current()]}destroyed.xml">
      <xsl:copy-of select=
       "($vResultNonDestroyed, $vResultDestroyed)[position() = current()]"/>
     </xsl:result-document>
   </xsl:for-each>
 </xsl:template>

 <xsl:template mode="destroyed" match="node[not(*/*/@action = 'destroy')]"/>
 <xsl:template mode="destroyed" match="node/*[not(*/@action = 'destroy')]"/>
 <xsl:template mode="destroyed" match="node/*/*[not(@action = 'destroy')]"/>

 <xsl:template mode="non-destroyed"  match="node[not(*/*/@action[not(. = 'destroy')])]"/>
 <xsl:template mode="non-destroyed"  match="node/*[not(*/@action[not(. = 'destroy')])]"/>
 <xsl:template mode="non-destroyed"  match="node/*/*[@action = 'destroy']"/>
</xsl:stylesheet>

当使用 Saxon 9.1.07 运行此转换时,正确的输出将写入文件

C:\Program Files\Java\jre6\bin\temp\delete\destroyed.xml

C:\Program Files\Java\jre6\bin\temp\delete\non-destroyed.xml

于 2012-05-06T15:32:25.383 回答