使用xslt复制xml输入的子集

时间:2012-03-21 22:46:05

标签: xslt copy nodes

我需要一个XSLT文件,用输入xml中的节点子集将输入xml转换为另一个。例如,如果输入有10个节点,我需要创建大约5个节点的输出 输入

  <Department diffgr:id="Department1" msdata:rowOrder="0">
    <Department>10</Department>
    <DepartmentDescription>BABY PRODUCTS</DepartmentDescription>
    <DepartmentSeq>7</DepartmentSeq>
    <InsertDateTime>2011-09-29T13:19:28.817-05:00</InsertDateTime>
   </Department>

输出:

  <Department diffgr:id="Department1" msdata:rowOrder="0">
    <Department>10</Department>
    <DepartmentDescription>BABY PRODUCTS</DepartmentDescription>
   </Department>

我找到了一种方法来抑制我们不需要的节点 XSLT:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

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

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

  <xsl:template match="Department/DepartmentSeq"/>
  <xsl:template match="Department/InsertDateTime"/>

</xsl:stylesheet>

我需要一个xslt来帮助我选择我需要的节点而不是“复制所有并过滤掉我不需要的东西”,因为每当输入架构添加更多节点时我可能不得不改变我的xslt。

更新

我发送的代码片段来自.NET Diffgram。完整的xml如下

输入:

<diffgr:diffgram xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1">
  <NewDataSet>
    <MessageHeader>
      <MessageID>201112270242029525719b93a-5fc5-42ce-8424-10764a4497ca</MessageID>
      <RequestType>Publish</RequestType>
      <ListOfApplications />
      <MessageType>MCH</MessageType>
    </MessageHeader>
    <Department diffgr:id="Department1" msdata:rowOrder="0">
      <Department>10</Department>
      <DepartmentDescription>BABY PRODUCTS</DepartmentDescription>
      <DepartmentSeq>7</DepartmentSeq>
      <InsertDateTime>2011-09-29T13:19:28.817-05:00</InsertDateTime>
      <UpdateDateTime>2011-09-30T11:50:59-05:00</UpdateDateTime>
      <InsertDateTimeUTC>2011-09-29T18:19:28.817-05:00</InsertDateTimeUTC>
    </Department>
    <Subclass diffgr:id="Subclass1" msdata:rowOrder="0" diffgr:hasChanges="modified">
      <Department>10</Department>
      <Category>03</Category>
      <Class>010</Class>
      <Subclass>03</Subclass>
      <SubclassLongDescription>BABY ACCESSORIES-OTHER LD TX 1120</SubclassLongDescription>
      <SubclassShortDescription>BABY ACCESSORIES-OTH</SubclassShortDescription>
    </Subclass>
  </NewDataSet>
  <diffgr:before>
    <Subclass diffgr:id="Subclass1" msdata:rowOrder="0">
      <Department>10</Department>
      <Category>03</Category>
      <Class>010</Class>
      <Subclass>03</Subclass>
      <SubclassLongDescription>BABY ACCESSORIES-OTHER LD TX 1120</SubclassLongDescription>
      <SubclassShortDescription>BABY ACCESSORIES-OTH</SubclassShortDescription>
    </Subclass>
  </diffgr:before>
</diffgr:diffgram>

提供了xslt Borodin,这是我得到的东西

<diffgr:diffgram xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
  <NewDataSet>
    <MessageHeader>
      <MessageID>201112270242029525719b93a-5fc5-42ce-8424-10764a4497ca</MessageID>
      <RequestType>Publish</RequestType>
      <ListOfApplications />
      <MessageType>MCH</MessageType>
    </MessageHeader>
    <Department diffgr:id="Department1" msdata:rowOrder="0">
      <Department>10</Department>
      <DepartmentDescription>BABY PRODUCTS</DepartmentDescription>
    </Department>
    <Subclass diffgr:id="Subclass1" msdata:rowOrder="0" diffgr:hasChanges="modified">
      <Department>10</Department>
      <Category>03</Category>
      <Class>010</Class>
      <Subclass>03</Subclass>
      <SubclassLongDescription>BABY ACCESSORIES-OTHER LD TX 1120</SubclassLongDescription>
      <SubclassShortDescription>BABY ACCESSORIES-OTH</SubclassShortDescription>
    </Subclass>
  </NewDataSet>
  <diffgr:before>
    <Subclass diffgr:id="Subclass1" msdata:rowOrder="0">
      <Department>10</Department>
      <Category>03</Category>
      <Class>010</Class>
      <Subclass>03</Subclass>
      <SubclassLongDescription>BABY ACCESSORIES-OTHER LD TX 1120</SubclassLongDescription>
      <SubclassShortDescription>BABY ACCESSORIES-OTH</SubclassShortDescription>
    </Subclass>
  </diffgr:before>
</diffgr:diffgram>

除了那些部门和部门描述标签,我不需要任何其他内容。为什么在xslt中未指定其他节点MessageHeader / subclass时会复制它们?

任何人都可以给我一个比上面更好的解决方案。添加像这样的每个节点是相当繁琐的,但如果没有其他可能的话,它会起作用。

4 个答案:

答案 0 :(得分:2)

我建议您使用标识转换,并使用特殊规则处理<Department>元素,以便您指定要复制的子项。这是一些示例代码。

<?xml version="1.0" encoding="UTF-8" ?>

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:output method="xml" indent="yes"/>

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

  <xsl:template match="Department[Department]">
    <xsl:copy>
      <xsl:apply-templates select="@*|Department|DepartmentDescription" />
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

我使用更新中的数据获得的输出如此

<?xml version="1.0" encoding="utf-8"?>
<diffgr:diffgram xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">

   <NewDataSet>

      <Department diffgr:id="Department1" msdata:rowOrder="0">
         <Department>10</Department>
         <DepartmentDescription>BABY PRODUCTS</DepartmentDescription>
      </Department>

   </NewDataSet>

</diffgr:diffgram>

答案 1 :(得分:1)

如果您只想匹配特定节点,而不是提供排除列表,则只需输入您需要的元素名称列表

<xsl:template match="Department|DepartmentSeq|InsertDateTime|@*">

因此,给出以下XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output omit-xml-declaration="yes"/>
   <xsl:template match="Department|DepartmentSeq|InsertDateTime|@*">
      <xsl:copy>
         <xsl:apply-templates select="node()|@*"/>
      </xsl:copy>
   </xsl:template>

   <xsl:template match="*" />
</xsl:stylesheet>

当应用于以下XML时(为了简化,我删除了名称空间前缀)

<Department id="Department1" rowOrder="0">
   <Department>10</Department>
   <DepartmentDescription>BABY PRODUCTS</DepartmentDescription>
   <DepartmentSeq>7</DepartmentSeq>
   <InsertDateTime>2011-09-29T13:19:28.817-05:00</InsertDateTime>
</Department>

输出以下内容。请注意,通过@ * match保留属性。

<Department id="Department1" rowOrder="0">
   <Department>10</Department>
   <DepartmentSeq>7</DepartmentSeq>
   <InsertDateTime>2011-09-29T13:19:28.817-05:00</InsertDateTime>
</Department>

请注意使用以下模板匹配,这将排除匹配列表中不存在的所有元素。如果没有这个,默认行为是输出元素的文本值

<xsl:template match="*" />

答案 2 :(得分:0)

此解决方案最适合我的输入

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

  </xsl:template>
  <xsl:template match="*" />

</xsl:stylesheet>

但是,我发现必须为层次结构中的每个节点编写匹配项非常麻烦。仍然有效,欢迎更好的解决方案!

答案 3 :(得分:0)

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1">
 <xsl:output indent="yes"/><xsl:strip-space elements="*"/>

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

  <!-- shutup unwanted elements -->
  <xsl:template match="MessageHeader
        | Subclass
        | InsertDateTime
        | UpdateDateTime
        | InsertDateTimeUTC
        | DepartmentSeq
        | diffgr:before"/>

 </xsl:stylesheet>