Umbenennen von Knoten mit XSLT

Ich versuche etwas sehr Einfaches, aber aus irgendeinem Grund funktioniert es nicht. Grundsätzlich muss ich einige Knoten in einem XML-Dokument umbenennen. Daher habe ich eine XSLT-Datei erstellt, um die Transformation zu tun.

Hier ist ein Beispiel für das XML:

EDIT: Adressen und Adresselemente treten auf vielen Ebenen auf. Dies hat mich dazu veranlasst, versuchen zu müssen, eine XSLT anzuwenden. Das Visual Studio-Typ-Dataset-Feature, das typisierte Datasets aus XSD-Dateien erstellt, erlaubt es Ihnen nicht, verschachtelte Verweise auf dieselbe Tabelle zu verwenden. Daher führt das Verhalten von Unternehmen/Unternehmen/Adressen und Unternehmen/Unternehmen/Kontakten/Adressen dazu, dass Load() fehlschlägt. Dies ist ein bekanntes Problem, und alles, was sie Ihnen sagen, ist so etwas wie "Haben Sie keine verschachtelten Tabellenreferenzen... Bearbeiten Sie Ihre XSD, um dies nicht mehr zu haben." Leider bedeutet dies, dass wir XSLT anwenden müssen, um das XML an die "gehackte" XSD anzupassen, da die Dateien von einem Drittanbieter stammen.

Also, wir sind sehr nah mit der Hilfe hier gemacht. Die letzten paar Dinge sind diese:

1.) Wie kann ich den Namespaceverweis im match-Attribut der xsl:template verwenden, um anzugeben, dass ich Unternehmen/Unternehmen/Adressen in BusinessAddresses umbenennen, aber Unternehmen/Unternehmen/Kontakte/Kontakte/Adressen in ContactAddresses umbenennen möchte?

2.) Wie kann ich verhindern, dass die XSLT jedes neue Element mit expliziten Namespace-Verweisen überträgt? Es verursacht extreme Aufblähung in der Ausgabe.

Ich habe einen Namespace namens "Stahl" erstellt und hatte guten Erfolg mit:

<xsl:template match="steel:Addresses>
  <xsl:element name="BusinessAddresses>
</xsl:template>

Das offensichtliche Problem hier ist, dass es ALLE der Adressen-Elemente in BusinessAddresses umbenennt, obwohl ich einige von ihnen ContactAddresses nennen möchte, und so weiter. Das unnötige Hinzufügen expliziter Namespaceverweise auf alle umbenannten Knoten ist ebenfalls problematisch.

Ich habe diese Art von Ding ausprobiert, aber sobald ich Schrägstriche zum Match-Attribut hinzufüge, ist es ein Syntaxfehler in der XSLT, wie so:

<xsl:template match="steel:/Businesses/Business/Addresses">

Ich fühle mich sehr nah, brauche aber eine Anleitung, wie man sowohl die Namespace-Nutzung als auch eine Möglichkeit, die Schrägstriche zu verwenden, um ANY Knoten unter bestimmten Pfaden auszuwählen.

<?xml version="1.0"?>
<Businesses>
  <Business>
    <BusinessName>Steel Stretching</BusinessName>
    <Addresses>
      <Address>
        <City>Pittsburgh</City>
      </Address>
      <Address>
        <City>Philadelphia</City>
      </Address>
    </Addresses>
    <Contacts>
      <Contact>
        <FirstName>Paul</FirstName>
        <LastName>Jones</LastName>
        <Addresses>
          <Address>
            <City>Pittsburgh</City>
          </Address>
        </Addresses>
      </Contact>
    </Contacts>
  </Business>
  <Business>
    <BusinessName>Iron Works</BusinessName>
    <Addresses>
      <Address>
        <City>Harrisburg</City>
      </Address>
      <Address>
        <City>Lancaster</City>
      </Address>
    </Addresses>
  </Business>
</Businesses>

Ich muss Adressen in BusinessAddresses umbenennen, und ich muss Adresse in BusinessAddress umbenennen, für jede Instanz von Adressen und Adressen direkt unter einem Business-Knoten. Außerdem muss ich Adressen in ContactAddresses umbenennen, und ich muss Die Adresse in ContactAddress umbenennen, für jede Instanz von Adressen und Adressen direkt unter einem Kontaktknoten.

Ich habe mehrere Lösungen ausprobiert, aber keine scheint zu funktionieren. Sie alle produzieren am Ende den gleichen XML-Code wie die Originaldatei.

Hier ist ein Beispiel für das, was ich ausprobiert habe:

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

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

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

Dies wurde in mindestens 6 verschiedenen Geschmacksrichtungen ausprobiert, komplett mit dem Durchlaufen des XSLT-Debuggers in VB.Net. Die Vorlagenübereinstimmung für Adressen wird nie ausgeführt.

Warum?

Antwort auf "Umbenennen von Knoten mit XSLT " 2 von antworten

Warum könnte ein XSLT fehlschlagen?

Eine XSLT scheitert an offensichtlichen Dingen wie Tippfehlern. Die wahrscheinlichste Situation bezieht sich jedoch auf die Verwendung von Namespace. Wenn Sie einen Standardnamespace für Ihre XML-Datei deklariert haben, diesen jedoch nicht in Ihre XSLT aufnehmen, stimmt die XSLT nicht wie erwartet mit den Vorlagen überein.

Im folgenden Beispiel wird das Attribut xmlns:business attribute which declares that items qualified by the hinzugefügt, das deklariert, dass Elemente, die durch das Präfix business prefix belong to the namespace qualifiziert sind, zum Namespace mynamespace.uri. I then used this prefix to qualify the Address and Addresses template matches. Of course, you will need to change the namespace URI to whatever matches the default namespace of your XML file. gehören. Ich habe dann dieses Präfix verwendet, um die Übereinstimmungen der Vorlage "Adresse" und "Adressen" zu qualifizieren. Natürlich müssen Sie den Namespace-URI in den Standardnamespace Ihrer XML-Datei ändern.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:msxsl="urn:schemas-microsoft-com:xslt"
                xmlns:business="mynamespace.uri"
                exclude-result-prefixes="msxsl">
  <xsl:template match="/">
    <xsl:apply-templates select="@*|node()"/>
  </xsl:template>

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

  <xsl:template match="business:Addresses">
    <xsl:element name="BusinessAddresses">
      <xsl:apply-templates select="@*|node()" />
    </xsl:element>
  </xsl:template>

  <xsl:template match="business:Address">
    <xsl:element name="BusinessAddress">
      <xsl:apply-templates select="@*|node()"/>
    </xsl:element>
  </xsl:template>
</xsl:stylesheet>

Wie stimmen Sie Vorlagen basierend auf elementsposition und Name ab?

Es gibt mehrere Möglichkeiten, diesen letzten Teil für Ihr Problem zu erreichen, BusinessAddress oder ContactAddress, aber am einfachsten ist es, die Vorlage match attributes to consider parent nodes. If you think of the Attribute zu ändern, um übergeordnete Knoten zu berücksichtigen. Wenn Sie sich das match attribute as a path into the XML for a node, this option becomes clearer (contents of templates left out for brevity): Attribut als Pfad in den XML-Code für einen Knoten vorstellen, wird diese Option klarer (Inhalt von Vorlagen, die aus Gründen der Kürze ausgelassen werden):

<xsl:template match="business:Business/business:Addresses>
</xsl:template>

<xsl:template match="business:Business/business:Addresses/business:Address">
</xsl:template>

<xsl:template match="business:Contact/business:Addresses">
</xsl:template>

<xsl:template match="business:Contact/business:Addresses/business:Address">
</xsl:template>

Andere Methoden, um dies zu erreichen, wenn das match remains based on just the element name, but they're harder to implement, follow, and maintain as they involve the use of conditional checks on the parent node hierarchy of the element being processing, all within the template. nur auf dem Elementnamen basiert, aber sie sind schwieriger zu implementieren, zu folgen und zu warten, da sie die Verwendung von bedingten Prüfungen auf der übergeordneten Knotenhierarchie des Elements beinhalten, das verarbeitet wird. , alle innerhalb der Vorlage.

Vielleicht ist dies, wenn die Daten, die Sie zeigen, wirklich so sind, wie Sie mit

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="Businesses">
 <Businesses>
  <xsl:apply-templates/>
 </Businesses>
</xsl:template>

<xsl:template match="*">
 <xsl:copy-of select="."/>
</xsl:template>

<xsl:template match="Addresses">
 <BusinessAddresses>
  <xsl:apply-templates/>
 </BusinessAddresses>
</xsl:template>

<xsl:template match="Addresses/Address">
 <BusinessAddress>
  <xsl:value-of select="."/>
 </BusinessAddress>
</xsl:template>

</xsl:stylesheet>      
arbeiten mussten.