【问题标题】:XSLT - Change child attribute if parent attribute contains specific textXSLT - 如果父属性包含特定文本,则更改子属性
【发布时间】:2021-12-28 18:45:03
【问题描述】:

我对 XSLT 非常陌生,完全不熟悉其背后的逻辑。 我有以下 XML:

<config>
  <connection port="4404" type="tcp">
      <selection name="test-mode" enabled="true"/>
  </connection>
  <connection port="4405" type="tcp">
      <selection name="test-mode" enabled="true"/>
  </connection>
  <connection port="4406" type="tcp">
      <selection name="test-mode" enabled="true"/>
  </connection>

  <option>
    <maxNumberOfDownloads>10</maxNumberOfDownload>
  </option>
  
</config>

应用XLST - Copy XML tag and replace attribute value 的一些转换后,我能够复制连接标签并根据之前的值更改端口属性。

<config>
  <connection port="4404" type="tcp">
    <selection name="test-mode" enabled="true"/>
  </connection>
  <connection port="7804" type="tcp">
    <selection name="test-mode" enabled="true"/>
  </connection>
  <connection port="4405" type="tcp">
    <selection name="test-mode" enabled="true"/>
  </connection>
  <connection port="7805" type="tcp">
    <selection name="test-mode" enabled="true"/>
  </connection>
  <connection port="4406" type="tcp">
    <selection name="test-mode" enabled="true"/>
  </connection>
  <connection port="7806" type="tcp">
    <selection name="test-mode" enabled="true"/>
  </connection>
  <option>
    <maxNumberOfDownloads>10</maxNumberOfDownloads>
  </option>
</config>

这是我的 XSLT:

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

    <!--  Initial template to copy all nodes and attributes  -->
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="connection[@port]">
        <xsl:copy>
            <!-- Copy all nodes and attributes -->
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
        <xsl:copy>
            <xsl:apply-templates select="@*"/>
            <xsl:attribute name="port">
                <xsl:value-of select="concat('78', substring(@port,3,2))"/>
            </xsl:attribute>
            <xsl:apply-templates/>
        </xsl:copy>
    </xsl:template>

   
</xsl:stylesheet>

目标:除了更改端口属性之外,我还尝试将属性enabled="false" 更改为新复制的元素(端口包含“78”的连接元素)

需要 XML 输出:

<config>
  <connection port="4404" type="tcp">
    <selection name="test-mode" enabled="true"/>
  </connection>
  <connection port="4405" type="tcp">
    <selection name="test-mode" enabled="true"/>
  </connection>
  <connection port="4406" type="tcp">
    <selection name="test-mode" enabled="true"/>
  </connection>
  <option>
    <maxNumberOfDownloads>10</maxNumberOfDownloads>
  </option>
  <connection port="7804" type="tcp">
    <selection name="test-mode" enabled="false"/>
  </connection>
  <connection port="7805" type="tcp">
    <selection name="test-mode" enabled="false"/>
  </connection>
  <connection port="7806" type="tcp">
    <selection name="test-mode" enabled="false"/>
  </connection>
</config>

有没有办法在复制的时候直接更新属性还是需要新建一个模板?

【问题讨论】:

  • 不清楚你的目标是什么。无论您是将@enabled="true"更改为false,还是只更改p@port或什么。您可以发布所需输出的示例吗?
  • @MadsHansen 添加了其他信息以澄清问题

标签: xml xslt


【解决方案1】:

可以一次性完成。

输入 XML

<config>
    <connection port="4404" type="tcp">
        <selection name="test-mode" enabled="true"/>
    </connection>
    <connection port="4405" type="tcp">
        <selection name="test-mode" enabled="true"/>
    </connection>
    <connection port="4406" type="tcp">
        <selection name="test-mode" enabled="true"/>
    </connection>

    <option>
        <maxNumberOfDownloads>10</maxNumberOfDownloads>
    </option>
</config>

XSLT

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

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

    <xsl:template match="connection[@port]">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
        <xsl:copy>
            <xsl:apply-templates select="@*"/>
            <xsl:attribute name="port">
                <xsl:value-of select="concat('78', substring(@port,3,2))"/>
            </xsl:attribute>
            <!--<xsl:apply-templates/>-->
            <selection>
                <xsl:apply-templates select="selection/@*"/>
                <xsl:attribute name="enabled">
                    <xsl:value-of select="'false'"/>
                </xsl:attribute>
            </selection>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

输出

<config>
  <connection port="4404" type="tcp">
    <selection name="test-mode" enabled="true"/>
  </connection>
  <connection port="7804" type="tcp">
    <selection name="test-mode" enabled="false"/>
  </connection>
  <connection port="4405" type="tcp">
    <selection name="test-mode" enabled="true"/>
  </connection>
  <connection port="7805" type="tcp">
    <selection name="test-mode" enabled="false"/>
  </connection>
  <connection port="4406" type="tcp">
    <selection name="test-mode" enabled="true"/>
  </connection>
  <connection port="7806" type="tcp">
    <selection name="test-mode" enabled="false"/>
  </connection>
  <option>
    <maxNumberOfDownloads>10</maxNumberOfDownloads>
  </option>
</config>

【讨论】:

  • 感谢您的明确答复。首先声明两次 的目的是什么?
  • `' 表示将子节点按原样复制到输出 XML。这就是为什么当我们需要将启用的属性值修改为“false”时,它被注释掉了。
猜你喜欢
  • 2021-10-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-13
  • 2015-03-24
  • 1970-01-01
相关资源
最近更新 更多