复制XML,同时排除父节点,删除特定的子节点并覆盖一些子节点

问题描述:

我已经审查了几个单独做这些事情的职位,但还没有成功将它们组合在一起。复制XML,同时排除父节点,删除特定的子节点并覆盖一些子节点

我也有类似的这种结构的输入:

<Response> 
    <Confirmation>Success</Confirmation> 
    <SecondResponse> 
     <InquiryResponse> 
      <ID>99999</ID> 
      <Confirmation>Success</Confirmation> 
      <Exception/> 
      <!-- The following structure repeats a varying amount of times --> 
      <DataNode1> 
      <!-- Child nodes could be null, transform should remove null nodes --> 
      <Child1>data</Child1> 
      ... 
      <Childn>dataN</Childn> 
      </DataNode1> 
      ... 
      <DataNodeN> 
      <Child1>data</Child1> 
      ... 
      <Childn>dataN</Childn> 
      </DataNodeN> 
     </InquiryResponse> 
    </SecondResponse> 
</Response> 

现在,我需要做到以下几点:

1)复制的<InquiryResponse>所有子节点(但不是<InquiryResponse>本身)

2)排除<Confirmation><Exception>节点

3)排除任何空chi ldren在数据管理部

4)在数据管理部插入一个新的子元素

因此所需的输出应该是这样的:

<ID>99999</ID> 
<DataNode1> 
    <Child1>data</Child1> 
    <ChiildInsert>newData</ChildInsert> 
    <Childn>dataN</Childn> 
</DataNode1> 
... 
<DataNodeN> 
    <Child1>data</Child1> 
    <ChildInsert>newData</ChildInsert> 
    <Childn>dataN</Childn> 
</DataNodeN> 

我相信我有做到这一点通过创建一个模板每个DataNode(我知道所有可能发生的值)以及用于删除不需要的节点的模板,然后将它们全部应用于忽略空节点的主副本模板。这是我目前的XSLT的化身,采用2.0 - 虽然我知道这并不完全是完整的,这是据我已经得到了:

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

    <!-- Remove Unwanted Nodes --> 
    <xsl:template match='Confirmation|Exception'/> 

    <!-- DataNode Template --> 
    <template match='DataNode1'> 
    <xsl:copy> 
     <xsl:apply-templates select="@*|node()"/> 
     <ChildInsert> 
      <xsl:value-of select='newData'/> 
     </ChildInsert> 
    </xsl:copy> 
    </xsl:template> 

    <!-- Identity Transform --> 
    <xsl:template match='@*|node()'> 
    <xsl:if test='. != ""'> 
     <xsl:copy> 
     <xsl:apply-templates select='@*|node()'/> 
     </xsl:copy> 
    </xsl:if> 
    </xsl:template> 

    </xsl:stylesheet> 

这是我使用撒克逊-PE 9.3产生输出.0.5

<Response> 
    <SecondResponse> 
    <InquiryResponse> 
     <ID>99999</ID> 
     <DataNode1> 
      <Child1>data</Child1> 
      <ChiildInsert>newData</ChildInsert> 
      <Childn>dataN</Childn> 
     </DataNode1> 
     .... 
     <DataNodeN>...</DataNodeN> 
    </InquiryResponse> 
    </SecondResponse> 
</Response> 

很明显,我仍然得到所有的回应父母,因为我没有指定一种方法来处理它们;但是,每当我尝试将模板匹配到XPath时,我都会获取数据,而不是XML。我知道我可以通过另一个转换,只是复制<InquiryResponse>的子节点,但我觉得应该有更优雅的方式来做到这一点。以下是我仍然面临的问题/问题。 1)由于使用这样的模板:<xsl:template match='Response'/>会使我的整个响应为空,我尝试切换识别模板以匹配Response/SecondResponse/InquiryResponse/*,但结果只产生文本数据而不是XML。

2)当<Exception>节点填充值时,它将继续被复制而不是像<Confirmation>节点那样被删除。 3)如果我想更新一个非空的子节点的值,我会这样做吗?还有一个额外的要求是更新一些儿童节点,所以我仍然在考虑如何去做,而这看起来是正确的方法,但我想验证一下。

<xsl:template match='childNodeA'> 
    <childNodeA> 
     <xsl:value-of select='someValue/> 
    </childNodeA> 
</xsl:template> 

我道歉,如果这还不清楚,但随时要求你做任何需要的进一步的细节和巨大的预先感谢您的人谁可以帮助。

您发布的输出XML格式不正确,因为它没有根元素,但是这个XSLT 1。0样式表应该做你想要什么:

样式

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

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

    <!-- Apply all child nodes; don't copy the element itself --> 
    <xsl:template match="Response | SecondResponse | InquiryResponse"> 
    <xsl:apply-templates/> 
    </xsl:template> 

    <!-- Drop elements --> 
    <xsl:template match="Confirmation | Exception"/> 

    <xsl:template match="DataNode1 | DataNode2 | DataNodeN"> 
    <xsl:copy> 
     <!-- Apply Child1, ignore children with no text content --> 
     <xsl:apply-templates select="Child1[normalize-space(.)]"/> 
     <!-- Insert new element --> 
     <ChildInsert>newData</ChildInsert> 
     <!-- Apply all other child elements except Child1 --> 
     <xsl:apply-templates select="*[normalize-space(.)][not(self::Child1)]"/> 
    </xsl:copy> 
    </xsl:template> 
</xsl:stylesheet> 

输入

<Response> 
    <Confirmation>Success</Confirmation> 
    <SecondResponse> 
    <InquiryResponse> 
     <ID>99999</ID> 
     <Confirmation>Success</Confirmation> 
     <Exception/> 
     <!-- The following structure repeats a varying amount of times --> 
     <DataNode1> 
      <!-- Child nodes could be null, transform should remove null nodes --> 
      <Child1>data</Child1> 
      <Childn>dataN</Childn> 
     </DataNode1> 
     <DataNodeN> 
      <Child1>data</Child1> 
      <Childn>dataN</Childn> 
     </DataNodeN> 
    </InquiryResponse> 
    </SecondResponse> 
</Response> 

输出

<?xml version="1.0" encoding="utf-8"?> 
<ID>99999</ID> 
<DataNode1> 
    <Child1>data</Child1> 
    <ChildInsert>newData</ChildInsert> 
    <Childn>dataN</Childn> 
</DataNode1> 
<DataNodeN> 
    <Child1>data</Child1> 
    <ChildInsert>newData</ChildInsert> 
    <Childn>dataN</Childn> 
</DataNodeN> 

请注意,由于您没有指定“null”的含义,因此我假设它指的是没有文本内容的元素。因此,上面的代码将像这样删除<Child1>元素:

<Child1> 
    <GrandChild1/> 
</Child1> 
+0

正确,“空白”节点应该是没有文本的节点。即。感谢您的回复,我会尽快进行测试! – 2013-02-18 17:16:56

+0

这几乎是完美的。我仍然得到SecondResponse和查询响应节点,并且我仍然遇到如果Exception节点具有文​​本,它仍然被复制的问题。任何想法是如何我可能无法拍摄这些物品?再次感谢! – 2013-02-19 22:03:29

+0

您是否使用了我粘贴的确切的XSLT样式表和输入文档?因为如果你是,如果你仍然遇到这些问题,我会感到非常惊讶。我尝试过使用'xsltproc'和Saxon 9.1.0.5J,它可以像两个处理器一样按预期工作。另一方面,如果你的样式表或输入文档不同,我将无法看到它们。顺便说一句,我无法用原始样式表重现'Exception'节点的问题。 – 2013-02-19 22:17:44