将子节点替换为另一个节点而不影响其子节点

问题描述 投票:0回答:1

我需要在不影响子节点的情况下用另一个节点替换子节点,我尝试匹配子节点,但无法做到

这是xml格式

<?xml version="1.0" encoding="UTF-8"?>
    <Envelope xmlns="http://schemas.microsoft.com/dynamics/2011/01/documents/Message">
    <Header>
    <MessageId>{A124-B421-C325-D467}</MessageId>
    <Action>find</Action> 
    </Header>
      <Body>
        <MessageParts xmlns="http://schemas.microsoft.com/dynamics/2011/01/documents/Message">
          <Run xmlns="http://schemas.microsoft.com/dynamics/2008/01/documents/Run">

            <RunObject class="entity">
              <A1>NA</A1>
              <A2>False</A2>
              <Object class="entity">
               <A3>02</A3>
              </Object>
              <A4>ER</A4>
            </RunObject>
          </Run>
        </MessageParts>
      </Body>
    </Envelope>

这是我需要的xml格式

<?xml version="1.0" encoding="UTF-8"?>
<Envelope xmlns="http://schemas.microsoft.com/dynamics/2011/01/documents/Message">
<Header>
<MessageId>{A124-B421-C325-D467}</MessageId>
<Action>find</Action> 
</Header>
<Body>
<Document>

      <Item>
        <A1>NA</A1>
        <A2>False</A2>
        <Base>
         <A3>02</A3>
        </Base>
        <A4>ER</A4>
      </Item>


</Document>
</Body>
</Envelope>

这是我尝试更改格式的代码

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:m="http://schemas.microsoft.com/dynamics/2011/01/documents/Message"
xmlns:r="http://schemas.microsoft.com/dynamics/2008/01/documents/Run"
exclude-result-prefixes="m r">
  <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
  <xsl:strip-space elements="*"/>
<!-- move all elements to no namespace -->
<xsl:template match="*">
    <xsl:element name="{local-name()}">
      <xsl:copy-of select="@*"/>
      <xsl:apply-templates/>
    </xsl:element>
  </xsl:template>


  <!-- rename MessageParts to Document + skip the Run wrapper -->
  <xsl:template match="m:MessageParts">
    <Document>
      <xsl:apply-templates select="r:Run/*"/>
    </Document>
  </xsl:template>
  <!-- rename RunObject to Item + reorder child nodes -->
  <xsl:template match="r:RunObject[@class='entity']">
    <Item>
      <xsl:apply-templates select="r:A1" />
      <xsl:apply-templates select="r:A2" />
      <xsl:template match="r:Object[@class='entity']>
       <Base>
       <xsl:apply-templates select="r:A3" />
       </Base>
      </xsl:Template>
      <xsl:apply-templates select="r:A4" />
    </Item>
  </xsl:template>
</xsl:stylesheet>

我尝试匹配Object元素,但是由于我已经匹配了它的父元素RunObject而无法进行此操作

xslt-1.0
1个回答
0
投票

您的错误是您无法在模板内部定义模板。因此,将<xsl:template match="r:Object[@class='entity']>移至根目录并在其位置添加<xsl:apply-templates select="r:Object" />

样式表可能看起来像这样:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:m="http://schemas.microsoft.com/dynamics/2011/01/documents/Message" xmlns:r="http://schemas.microsoft.com/dynamics/2008/01/documents/Run" exclude-result-prefixes="m r">
  <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
  <xsl:strip-space elements="*"/>

  <!-- move all elements to no namespace -->
  <xsl:template match="*">
    <xsl:element name="{local-name()}">
      <xsl:copy-of select="@*"/>
      <xsl:apply-templates/>
    </xsl:element>
  </xsl:template>

  <!-- rename MessageParts to Document + skip the Run wrapper -->
  <xsl:template match="m:MessageParts">
    <Document>
      <xsl:apply-templates select="r:Run/*"/>
    </Document>
  </xsl:template>

  <!-- rename RunObject to Item + reorder child nodes -->
  <xsl:template match="r:RunObject[@class='entity']">
    <Item>
      <xsl:apply-templates select="r:A1" />
      <xsl:apply-templates select="r:A2" />
      <xsl:apply-templates select="r:Object" />
      <xsl:apply-templates select="r:A4" />
    </Item>
  </xsl:template>

  <xsl:template match="r:Object[@class='entity']">
    <Base>
        <xsl:apply-templates select="r:A3" />
    </Base>
  </xsl:template>

</xsl:stylesheet>

其输出(几乎)是所需的:

<?xml version="1.0" encoding="UTF-8"?>
<Envelope>
    <Header>
        <MessageId>{A124-B421-C325-D467}</MessageId>
        <Action>find</Action>
    </Header>
    <Body>
        <Document>
            <Item>
                <A1>NA</A1>
                <A2>False</A2>
                <Base>
                    <A3>02</A3>
                </Base>
                <A4>ER</A4>
            </Item>
        </Document>
    </Body>
</Envelope>

我添加了形容词“ nearly”,因为此结果没有名称空间,而所需结果的示例在名称空间中

xmlns:m="http://schemas.microsoft.com/dynamics/2011/01/documents/Message"

但是因为您定义了删除所有元素的名称空间的模板,所以我确实忽略了这一点。我只是假设您的问题的这一部分是错误的。


如果您想更改它,请限制第一个模板并添加一个常规的身份模板

<!-- move all elements to no namespace -->
<xsl:template match="*[namespace-uri() != 'http://schemas.microsoft.com/dynamics/2011/01/documents/Message']">
    <xsl:element name="{local-name()}">
      <xsl:copy-of select="@*"/>
      <xsl:apply-templates/>
    </xsl:element>
</xsl:template>

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

这将使您的输出包含根名称空间:

<?xml version="1.0" encoding="UTF-8"?>
<Envelope xmlns="http://schemas.microsoft.com/dynamics/2011/01/documents/Message">
    <Header>
        <MessageId>{A124-B421-C325-D467}</MessageId>
        <Action>find</Action>
    </Header>
    <Body>
        <Document xmlns="">
            <Item>
                <A1>NA</A1>
                <A2>False</A2>
                <Base>
                    <A3>02</A3>
                </Base>
                <A4>ER</A4>
            </Item>
        </Document>
    </Body>
</Envelope>
© www.soinside.com 2019 - 2024. All rights reserved.