Search code examples
xmlxslt-1.0

Remove an element based on elements of sibling


I have data from water-pipes, in my example two valves ("Absperrorgan") and 4 text-labels. The first valve "101" has one label "xx", the valve "cd" has labels "202" and "999" and the the last label has no further info. Here is the data (with special namespace and looong strings):

<?xml version="1.0" encoding="utf-8"?>
<TRANSFER xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.interlis.ch/INTERLIS2.3" xmlns="http://www.interlis.ch/INTERLIS2.3">
  <HEADERSECTION VERSION="2.3" SENDER="xx">
    <MODELS>
      <MODEL NAME="SIA405_WASSER_2015_LV95" VERSION="05.10.2018" URI="http://www.sia.ch/405" />
    </MODELS>
  </HEADERSECTION>
  <DATASECTION>
    <SIA405_WASSER_2015_LV95.SIA405_Wasser BID="1111">
      <SIA405_WASSER_2015_LV95.SIA405_Wasser.Absperrorgan TID="ab">
        <OBJ_ID>ab</OBJ_ID>
      </SIA405_WASSER_2015_LV95.SIA405_Wasser.Absperrorgan>
      <SIA405_WASSER_2015_LV95.SIA405_Wasser.Absperrorgan TID="cd">
        <OBJ_ID>cd</OBJ_ID>
      </SIA405_WASSER_2015_LV95.SIA405_Wasser.Absperrorgan>
      <SIA405_WASSER_2015_LV95.SIA405_Wasser.Leitungsknoten_Text TID="xx">
        <Textinhalt>101</Textinhalt>
        <LeitungsknotenRef REF="ab" />
      </SIA405_WASSER_2015_LV95.SIA405_Wasser.Leitungsknoten_Text>
      <SIA405_WASSER_2015_LV95.SIA405_Wasser.Leitungsknoten_Text TID="yy">
        <Textinhalt>202</Textinhalt>
        <LeitungsknotenRef REF="cd" />
      </SIA405_WASSER_2015_LV95.SIA405_Wasser.Leitungsknoten_Text>
      <SIA405_WASSER_2015_LV95.SIA405_Wasser.Leitungsknoten_Text TID="test">
        <Textinhalt>999</Textinhalt>
        <LeitungsknotenRef REF="cd" />
      </SIA405_WASSER_2015_LV95.SIA405_Wasser.Leitungsknoten_Text>
      <SIA405_WASSER_2015_LV95.SIA405_Wasser.Leitungsknoten_Text TID="zz">
        <Textinhalt>303</Textinhalt>
        <LeitungsknotenRef REF="nix" />
      </SIA405_WASSER_2015_LV95.SIA405_Wasser.Leitungsknoten_Text>
    </SIA405_WASSER_2015_LV95.SIA405_Wasser>
  </DATASECTION>
</TRANSFER>

What is my target? "Remove all "Text-elements" which belong to valves". It should look like this:

<?xml version="1.0" encoding="utf-8"?>
<TRANSFER xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.interlis.ch/INTERLIS2.3" xmlns="http://www.interlis.ch/INTERLIS2.3">
  <HEADERSECTION VERSION="2.3" SENDER="xx">
    <MODELS>
      <MODEL NAME="SIA405_WASSER_2015_LV95" VERSION="05.10.2018" URI="http://www.sia.ch/405" />
    </MODELS>
  </HEADERSECTION>
  <DATASECTION>
    <SIA405_WASSER_2015_LV95.SIA405_Wasser BID="1111">
      <SIA405_WASSER_2015_LV95.SIA405_Wasser.Absperrorgan TID="ab">
        <OBJ_ID>ab</OBJ_ID>
      </SIA405_WASSER_2015_LV95.SIA405_Wasser.Absperrorgan>
      <SIA405_WASSER_2015_LV95.SIA405_Wasser.Absperrorgan TID="cd">
        <OBJ_ID>cd</OBJ_ID>
      </SIA405_WASSER_2015_LV95.SIA405_Wasser.Absperrorgan>
      <SIA405_WASSER_2015_LV95.SIA405_Wasser.Leitungsknoten_Text TID="zz">
        <Textinhalt>303</Textinhalt>
        <LeitungsknotenRef REF="nix" />
      </SIA405_WASSER_2015_LV95.SIA405_Wasser.Leitungsknoten_Text>
    </SIA405_WASSER_2015_LV95.SIA405_Wasser>
  </DATASECTION>
</TRANSFER>

In Detail: Remove all elements "SIA405_WASSER_2015_LV95.SIA405_Wasser.Leitungsknoten_Text" where its child-element "LeitungsknotenRef" has an attribute "REF" which is the same in "SIA405_WASSER_2015_LV95.SIA405_Wasser/SIA405_WASSER_2015_LV95.SIA405_Wasser.Absperrorgan/OBJ_ID" (The REF of a text shows to which object (valve) is belongs")

My XSLT:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:ili="http://www.interlis.ch/INTERLIS2.3" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output omit-xml-declaration="yes" indent="yes" />
  <xsl:strip-space elements="*" />
  <xsl:template match="node()|@*">
    <xsl:copy>
      <xsl:apply-templates select="node()|@*" />
    </xsl:copy>
  </xsl:template>
  <xsl:template match="ili:SIA405_WASSER_2015_LV95.SIA405_Wasser/ili:SIA405_WASSER_2015_LV95.SIA405_Wasser.Leitungsknoten_Text/ili:LeitungsknotenRef[@REF = preceding-sibling::ili:SIA405_WASSER_2015_LV95.SIA405_Wasser/ili:SIA405_WASSER_2015_LV95.SIA405_Wasser.Absperrorgan/ili:OBJ_ID]"></xsl:template>
</xsl:stylesheet>

What's the idea behind it? a) Copy everything (identity) but b) ignore the elements where its REF is the same of the OBJ_ID of one of its siblings (usually preceding, but that's not fixed)

What's the current result? a) it copies everything b) but does not match the REF=OBJ_ID definition

I'm not sure if my basic idea is a good one. Look value in text - try to find it in valves - go back and ignore ..

Thanks in advance to reduce my confusion!


Solution

  • Please try the following solution.

    Input XML

    <?xml version="1.0" encoding="utf-8"?>
    <TRANSFER xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://www.interlis.ch/INTERLIS2.3"
              xmlns="http://www.interlis.ch/INTERLIS2.3">
        <HEADERSECTION VERSION="2.3" SENDER="xx">
            <MODELS>
                <MODEL NAME="SIA405_WASSER_2015_LV95" VERSION="05.10.2018"
                       URI="http://www.sia.ch/405"/>
            </MODELS>
        </HEADERSECTION>
        <DATASECTION>
            <SIA405_WASSER_2015_LV95.SIA405_Wasser BID="1111">
                <SIA405_WASSER_2015_LV95.SIA405_Wasser.Absperrorgan TID="ab">
                    <OBJ_ID>ab</OBJ_ID>
                </SIA405_WASSER_2015_LV95.SIA405_Wasser.Absperrorgan>
                <SIA405_WASSER_2015_LV95.SIA405_Wasser.Absperrorgan TID="cd">
                    <OBJ_ID>cd</OBJ_ID>
                </SIA405_WASSER_2015_LV95.SIA405_Wasser.Absperrorgan>
                <SIA405_WASSER_2015_LV95.SIA405_Wasser.Leitungsknoten_Text TID="xx">
                    <Textinhalt>101</Textinhalt>
                    <LeitungsknotenRef REF="ab"/>
                </SIA405_WASSER_2015_LV95.SIA405_Wasser.Leitungsknoten_Text>
                <SIA405_WASSER_2015_LV95.SIA405_Wasser.Leitungsknoten_Text TID="yy">
                    <Textinhalt>202</Textinhalt>
                    <LeitungsknotenRef REF="cd"/>
                </SIA405_WASSER_2015_LV95.SIA405_Wasser.Leitungsknoten_Text>
                <SIA405_WASSER_2015_LV95.SIA405_Wasser.Leitungsknoten_Text TID="test">
                    <Textinhalt>999</Textinhalt>
                    <LeitungsknotenRef REF="cd"/>
                </SIA405_WASSER_2015_LV95.SIA405_Wasser.Leitungsknoten_Text>
                <SIA405_WASSER_2015_LV95.SIA405_Wasser.Leitungsknoten_Text TID="zz">
                    <Textinhalt>303</Textinhalt>
                    <LeitungsknotenRef REF="nix"/>
                </SIA405_WASSER_2015_LV95.SIA405_Wasser.Leitungsknoten_Text>
            </SIA405_WASSER_2015_LV95.SIA405_Wasser>
        </DATASECTION>
    </TRANSFER>
    

    XSLT 1.0

    <?xml version="1.0"?>
    <xsl:stylesheet version="1.0"
                    xmlns:ili="http://www.interlis.ch/INTERLIS2.3"
                    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:output omit-xml-declaration="yes" indent="yes"/>
        <xsl:strip-space elements="*"/>
    
        <xsl:template match="node()|@*">
            <xsl:copy>
                <xsl:apply-templates select="node()|@*"/>
            </xsl:copy>
        </xsl:template>
    
        <xsl:template match="ili:SIA405_WASSER_2015_LV95.SIA405_Wasser.Leitungsknoten_Text[ili:LeitungsknotenRef/@REF=//ili:SIA405_WASSER_2015_LV95.SIA405_Wasser.Absperrorgan/ili:OBJ_ID]"/>
    </xsl:stylesheet>
    

    Output XML

    <TRANSFER xmlns="http://www.interlis.ch/INTERLIS2.3" xsi:schemaLocation="http://www.interlis.ch/INTERLIS2.3" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
      <HEADERSECTION SENDER="xx" VERSION="2.3">
        <MODELS>
          <MODEL NAME="SIA405_WASSER_2015_LV95" VERSION="05.10.2018" URI="http://www.sia.ch/405"/>
        </MODELS>
      </HEADERSECTION>
      <DATASECTION>
        <SIA405_WASSER_2015_LV95.SIA405_Wasser BID="1111">
          <SIA405_WASSER_2015_LV95.SIA405_Wasser.Absperrorgan TID="ab">
            <OBJ_ID>ab</OBJ_ID>
          </SIA405_WASSER_2015_LV95.SIA405_Wasser.Absperrorgan>
          <SIA405_WASSER_2015_LV95.SIA405_Wasser.Absperrorgan TID="cd">
            <OBJ_ID>cd</OBJ_ID>
          </SIA405_WASSER_2015_LV95.SIA405_Wasser.Absperrorgan>
          <SIA405_WASSER_2015_LV95.SIA405_Wasser.Leitungsknoten_Text TID="zz">
            <Textinhalt>303</Textinhalt>
            <LeitungsknotenRef REF="nix"/>
          </SIA405_WASSER_2015_LV95.SIA405_Wasser.Leitungsknoten_Text>
        </SIA405_WASSER_2015_LV95.SIA405_Wasser>
      </DATASECTION>
    </TRANSFER>