【问题标题】:Removing elements from nodes or nodes from xml when attribute and text content match using xslt 2.0当属性和文本内容匹配时,使用 xslt 2.0 从节点或节点中删除元素
【发布时间】:2023-03-26 12:54:01
【问题描述】:

我在转换 xml 时遇到了困难。这是我的xml:

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <organisation>
        <school>
            <name>school of arts Berlin</name>
            <address>123street</address>
        </school>
    </organisation>
    <teachers>
        <wo_number>34A</wo_number>
        <publication>
            <date>14-09-2018</date>
            <name>J. doe</name>
        </publication>
        <teacher id="A254">
            <situation>
                <ill>yes</ill>
            </situation>
            <situation>
                <ill>no</ill>
            </situation>
            <situation>
                <ill>probable</ill>
            </situation>
        </teacher>
        <teacher id="A254">
            <situation>
                <ill>yes</ill>
            </situation>
            <situation>
                <ill>yes</ill>
            </situation>
        </teacher>
        <teacher id="B254">
            <situation>
                <ill>probable</ill>
            </situation>
        </teacher>
        <teacher id="X92">
            <situation>
                <ill>no</ill>
            </situation>
            <situation>
                <ill>probable</ill>
            </situation>
        </teacher>
        <teacher id="G56">
            <situation>
                <ill>probable</ill>
            </situation>
            <situation>
                <ill>no</ill>
        </situation>
        </teacher>
        <teacher id="G56">
            <situation>
                <ill>yes</ill>
            </situation>
        </teacher>
        <teacher id="G56">
            <situation>
                <ill>probable</ill>
            </situation>
        </teacher>
    </teachers>
</root>

我想要达到的目标:

  • teacher 元素有一个属性 id,如果它以“A2”开头并且同一教师节点中的元素 ill 的文本内容等于“yes”,则必须删除情境节点。如果教师节点中没有情景节点,则必须删除教师节点
  • teacher 元素有一个属性 id,如果它以“G5”开头并且同一教师节点中的元素 ill 的文本内容等于“probable”,则必须删除情境节点。如果教师节点中没有情景节点,则必须删除教师节点

正确的结果应该是:

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <organisation>
        <school>
            <name>school of arts Berlin</name>
            <address>123street</address>
        </school>
    </organisation>
    <teachers>
        <wo_number>34A</wo_number>
        <publication>
            <date>14-09-2018</date>
            <name>J. doe</name>
        </publication>
        <teacher id="A254">
            <situation>
                <ill>no</ill>
            </situation>
            <situation>
                <ill>probable</ill>
            </situation>
        </teacher>
        <teacher id="B254">
            <situation>
                <ill>probable</ill>
            </situation>
        </teacher>
        <teacher id="X92">
            <situation>
                <ill>no</ill>
            </situation>
            <situation>
                <ill>probable</ill>
            </situation>
        </teacher>
        <teacher id="G56">
            <situation>
                <ill>no</ill>
            </situation>
        </teacher>
        <teacher id="G56">
            <situation>
                <ill>yes</ill>
            </situation>
        </teacher>
    </teachers>
</root>

到目前为止,我还没有做到这一点。我的 xslt 现在是:

    <xsl:stylesheet version="2.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="teacher[starts-with(@id,'A2') and situation/ill='yes']"/>
      <xsl:template match="teacher[starts-with(@id,'G5') and situation/ill='probable']"/>
    </xsl:stylesheet>

有了这个结果:

    <root>
        <organisation>
            <school>
                <name>school of arts Berlin</name>
                <address>123street</address>
            </school>
        </organisation>
        <teachers>
            <wo_number>34A</wo_number>
            <publication>
                <date>14-09-2018</date>
                <name>J. doe</name>
            </publication>


            <teacher id="B254">
                <situation>
                    <ill>probable</ill>
                </situation>
            </teacher>
            <teacher id="X92">
                <situation>
                    <ill>no</ill>
                </situation>
            </teacher>
            <teacher id="G56">
                <situation>
                    <ill>yes</ill>
                </situation>
            </teacher>

        </teachers>
    </root>

所有教师节点 id="A254" 被删除,这是不正确的,带有id="G56" 的教师节点也被删除,这也是不正确的。非常感谢一些帮助。

【问题讨论】:

    标签: xml xslt


    【解决方案1】:

    作为替代方案,当您正在寻找 XSLT 2 解决方案时,您可能会使用 Saxon 9 或 Altova,其中最新版本也支持 XSLT 3,您可以使用 XSLT 3 xsl:where-populated https://www.w3.org/TR/xslt-30/#element-where-populated 以确保仅那些teacher 元素创建内容并处理其子元素创建输出:

    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        version="3.0">
    
      <xsl:strip-space elements="*"/>
      <xsl:output indent="yes"/>
    
      <xsl:mode on-no-match="shallow-copy"/>
    
      <xsl:template match="teacher[starts-with(@id, 'A2')] | teacher[starts-with(@id, 'G5')]">
          <xsl:where-populated>
              <xsl:next-match/>
          </xsl:where-populated>
      </xsl:template>
    
      <xsl:template match="teacher[starts-with(@id, 'A2')]/situation[ill = 'yes'] |
                           teacher[starts-with(@id, 'G5')]/situation[ill = 'probable']"/>
    
    </xsl:stylesheet>
    

    https://xsltfiddle.liberty-development.net/gWmuiJ9 的在线演示。

    【讨论】:

    • 我必须使用 2.0,但不幸的是我尝试了您的解决方案,它给了我 2 个错误: XTSE0010:元素 不允许作为元素 的子元素 XTSE0010:元素 不允许作为元素
    • @fasln01,我想我清楚地表明xsl:where-populated 是 XSLT 3 中的一个新功能,我还解释了哪些处理器支持它(最新版本的 Saxon 9,目前是 9.8,或 Altova ,目前是 2018 版本)。所以我的回答是作为一种替代方案,以防你仍然使用这些版本。 XSLT Fiddle 工具使用 Saxon 9.8 HE,因此它支持 XSLT 3。
    • 是的,你很清楚,我知道你的意图。我渴望探索您的解决方案,我使用 altova xmlspy 和 3.0 xslt 模板但显然它没有 2018 版本。谢谢你的解决方案马丁
    【解决方案2】:

    此解决方案需要对空模板进行一些微调。

    前两个模板检查teacher 元素是否在situation/ill 子元素中具有所有yesprobable 值,如果是,则删除它们。通过将子项的计数与匹配的子项的计数进行比较来执行检查。

    另外两个模板检查situation 元素,这些元素只有一个ill 元素包含yesprobable。如果是这样,则仅删除 situation 元素,而不是整个 teacher 元素。

    <xsl:template match="teacher[starts-with(@id,'A2') and situation/ill='yes' and count(situation[ill='yes']) = count(situation/ill)]" />      
    <xsl:template match="teacher[starts-with(@id,'G5') and situation/ill='probable' and count(situation[ill='probable']) = count(situation/ill)]" />
    <xsl:template match="situation[starts-with(../@id,'A2') and ill='yes']"/>      
    <xsl:template match="situation[starts-with(../@id,'G5') and ill='probable']"/>   
    

    【讨论】:

      【解决方案3】:
      <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
          xmlns:xs="http://www.w3.org/2001/XMLSchema"
          exclude-result-prefixes="xs"
          version="2.0">
          <xsl:output method="xml" indent="yes"/>
          <xsl:strip-space elements="*"/>
          <xsl:template match="@*|node()">
              <xsl:copy>
                  <xsl:apply-templates select="@*|node()"/>
              </xsl:copy>
          </xsl:template>
          <xsl:template match="root">
              <xsl:element name="root">
              <xsl:element name="organisation">
                  <xsl:element name="school">
                      <xsl:element name="name">
                          <xsl:value-of select="organisation/school/name"/>
                      </xsl:element>
                      <xsl:element name="address">
                          <xsl:value-of select="organisation/school/address"/>
                      </xsl:element>
                  </xsl:element>
              </xsl:element>
              <xsl:element name="teachers">
                  <xsl:element name="wo_number">
                      <xsl:value-of select="teachers/wo_number"/>
                  </xsl:element>
                  <xsl:element name="publication">
                      <xsl:element name="date">
                          <xsl:value-of select="teachers/publication/date"/>
                      </xsl:element>
                      <xsl:element name="name">
                          <xsl:value-of select="teachers/publication/name"/>
                      </xsl:element>
                  </xsl:element>
      
      
              <xsl:for-each select="teachers/teacher">
                  <xsl:choose>
                      <xsl:when test=" starts-with(@id,'A2')">
                          <xsl:choose>
                              <xsl:when test="situation/ill='no'">
                                  <xsl:element name="teacher">
                                      <xsl:attribute name="id">
                                          <xsl:value-of select="@id"/>
                                      </xsl:attribute>
      
                                  <situation>
                                      <xsl:element name="ill">
                                          <xsl:value-of select="situation[ill='no']"/>
                                      </xsl:element>
                                  </situation>
                                  <situation>
                                      <xsl:element name="ill">
                                          <xsl:value-of select="situation[ill='probable']"/>
                                      </xsl:element>
                                  </situation>
                                  </xsl:element>
                              </xsl:when>
      
                              <xsl:when test="situation/ill='yes'"/>
                          </xsl:choose>   
                      </xsl:when>
                      <!--<xsl:when test=" starts-with(@id,'A2') and situation/ill='yes'"/>-->
      
                      <xsl:when test="starts-with(@id,'G5')">
                          <xsl:choose>
      
                              <xsl:when test="situation/ill='no'">
                                  <xsl:element name="teacher">
                                      <xsl:attribute name="id">
                                          <xsl:value-of select="@id"/>
                                      </xsl:attribute>
      
                                      <situation>
                                          <xsl:element name="ill">
                                              <xsl:value-of select="situation[ill='no']"/>
                                          </xsl:element>
                                      </situation>
                                  </xsl:element>
                              </xsl:when>
                              <xsl:when test="situation/ill='yes'">
                                  <xsl:element name="teacher">
                                      <xsl:attribute name="id">
                                          <xsl:value-of select="@id"/>
                                      </xsl:attribute>
      
                                      <situation>
                                          <xsl:element name="ill">
                                              <xsl:value-of select="situation[ill='yes']"/>
                                          </xsl:element>
                                      </situation>
                                  </xsl:element>
                              </xsl:when>
                              <xsl:when test="situation/ill='probable'"/>
                          </xsl:choose>
                      </xsl:when>
                      <xsl:otherwise>
                          <xsl:copy-of select="."/>
                      </xsl:otherwise>
                  </xsl:choose>
              </xsl:for-each>
              </xsl:element>
              </xsl:element>
          </xsl:template>
      </xsl:stylesheet>
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-11-23
        • 1970-01-01
        • 2015-08-30
        • 1970-01-01
        • 2016-10-11
        • 2017-07-11
        相关资源
        最近更新 更多