2

我想从 xml 中删除空属性,还需要根据特定元素对其进行拆分。我创建了两个 xsl 用于分别拆分和删除空属性,它工作正常。但我需要将这两个 xsl 组合起来,以便在删除空属性后,需要根据特定元素拆分 xml。

删除属性 xslt:

 <xsl:template match="node()|@*">        

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

 <xsl:template match="@*[not(normalize-space(.))]">

  <xsl:if test="descendant::*/@*[not(normalize-space(.))]">
     <xsl:copy />
  </xsl:if>

 </xsl:template>
 </xsl:stylesheet>

拆分 XSLT:

 <?xml version="1.0" encoding="ISO-8859-1"?>
  <xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"        
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

   <xsl:output omit-xml-declaration="yes" indent="yes"/>



   <xsl:template match="/*" >


   <xsl:result-document href="ure.xml">
    <xsl:element name="Employee" >
        <xsl:attribute name="xsi:schemaLocation">sample.xsd</xsl:attribute>
        <xsl:copy-of select="/Employee/*"/>          
    </xsl:element>


</xsl:result-document>

     </xsl:template>


    </xsl:stylesheet>

输入 XML:

  <?xml version="1.0" encoding="UTF-8"?>
  <Enroll>
   <Department id="x1" name="">
      <members id ="" name="lio">ds</members>
   </Department>
    <Employee>
    <address id="s1" no=""></address>
    <domain id="" no="34"></domain>
    </Employee>
  </Enroll> 

output_one xml:

   <Department id="x1" name="">
      <members id ="" name="lio">ds</members>
   </Department>

输出+_two Xml:

   <Employee>
    <address id="s1" ></address>
    <domain  no="34"></domain>
   </Employee>

输出应该是两个单独的 xml 文件,其中应该有拆分的 xml 部分,并且需要删除空属性。

我已经尝试使用 Apply-templates、include 和 xml 管道,但我无法让它工作。

任何帮助将不胜感激。

4

2 回答 2

2

我将提供 XProc 替代方案,因为您使用 XProc 标记了问题。以下保留了 Employee 元素:

<p:declare-step version="1.0" xmlns:p="http://www.w3.org/ns/xproc">
    <p:input port="source"/>
    <p:output port="result"/>

    <p:delete match="@*[normalize-space(.) = '']"/>
    <p:filter select="//Employee"/>
</p:declare-step>

您可以使用 XMLCalabash 使用如下命令行执行它:

calabash --input source=in.xml --output result=employee.xml test.xpl

它确实假设您的输入中只有一个 Employee 元素。否则,它将尝试将多个 Employee 元素写入单个文件。它首先会抱怨结果输出端口不接受序列。

如果您添加sequence="true"它,而不进行任何进一步的更改,您最终会得到格式不正确的 XML,就像 JLRishe 的 XSLT 方法一样。在这种情况下,您需要使用p:wrap-sequence、 或 use来包装 Employee 元素的序列p:for-each,以及p:store将单个员工写入磁盘之类的东西。

注意:如果您是 XProc 的新手,最后一段可能会有点简洁。让我知道是否需要详细说明..

添加:

如果要使用 XProc 保存 Department 和 Employee 元素,可以使用以下内容:

<p:declare-step version="1.0" xmlns:p="http://www.w3.org/ns/xproc">

    <p:input port="source"/>
    <p:output port="employees">
        <p:pipe step="employees" port="result"/>
    </p:output>
    <p:output port="departments" primary="true"/>

    <p:delete match="@*[normalize-space(.) = '']" name="cleaned"/>

    <p:filter select="//Employee"/>
    <p:wrap-sequence wrapper="Employees" name="employees"/>

    <p:filter select="//Department">
        <p:input port="source">
            <p:pipe step="cleaned" port="result"/>
        </p:input>
    </p:filter>
    <p:wrap-sequence wrapper="Departments"/>

</p:declare-step>

您可以使用 XMLCalabash 使用如下命令行执行它:

calabash --input source=in.xml --output employees=employees.xml --output departments.xml test2.xpl

代码仍然遵循相同的流程,但员工输出端口是非主要的,并且必须显式绑定到员工步骤的结果。部门过滤使用显式输入端口绑定来不将“员工”的结果作为输入,而是使用“清理”步骤。所有其他输入和输出都根据约定自动绑定。

注意:我添加p:wrap-sequence以使其更健壮。您可以删除这些,前提是您将员工的姓名属性从其前面p:wrap-sequence移到..p:filter

于 2014-01-08T14:59:49.260 回答
2

这应该完成您所描述的内容:

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

  <xsl:output omit-xml-declaration="yes" indent="yes"/>

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

  <xsl:template match="Employee//@*[not(normalize-space())]" />

  <xsl:template match="/*" >

    <xsl:result-document href="output_one.xml">
      <xsl:apply-templates select="Department" />
    </xsl:result-document>

    <xsl:result-document href="output_two.xml">
      <xsl:apply-templates select="Employee" />
    </xsl:result-document>

  </xsl:template>

</xsl:stylesheet>

在您提供的输入上运行时,结果是:

output_one.xml:

<Department id="x1" name="">
    <members id="" name="lio">ds</members>
</Department>

output_two.xml:

<Employee>
  <address id="s1" />
  <domain no="34" />
</Employee>
于 2014-01-08T13:59:21.893 回答