Frage

Ich habe ein XML -Dokument und möchte die Werte für eines der Attribute ändern.

Zuerst habe ich alles von der Eingabe bis zur Ausgabe kopiert mit:

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

Und jetzt möchte ich den Wert des Attributs ändern "type" In jedem Element namens "property".

War es hilfreich?

Lösung

Auf ein einfaches Beispiel funktioniert einwandfrei:

<xsl:template match="@*|node()">
  <xsl:copy>
    <xsl:apply-templates select="@*|node()"/>
  </xsl:copy>
</xsl:template>
<xsl:template match="@type[parent::property]">
  <xsl:attribute name="type">
    <xsl:value-of select="'your value here'"/>
  </xsl:attribute>
</xsl:template>

Bearbeitet, um Tomalaks Vorschlag aufzunehmen.

Andere Tipps

Dieses Problem hat eine klassische Lösung: Verwenden und Überschreiben das Identitätsvorlage ist eines der grundlegendsten und leistungsstärksten XSLT -Designmuster:

<xsl:stylesheet version="1.0" 
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>

    <xsl:param name="pNewType" select="'myNewType'"/>

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

    <xsl:template match="property/@type">
        <xsl:attribute name="type">
            <xsl:value-of select="$pNewType"/>
        </xsl:attribute>
    </xsl:template>
</xsl:stylesheet>

Bei diesem XML -Dokument angewendet:

<t>
  <property>value1</property>
  <property type="old">value2</property>
</t>

Das gewünschte Ergebnis wird produziert:

<t>
  <property>value1</property>
  <property type="myNewType">value2</property>
</t>

Die beiden besten Antworten funktionieren nicht, wenn im Stammelement eine XMLNS -Definition vorhanden ist:

<?xml version="1.0"?>
<html xmlns="http://www.w3.org/1999/xhtml">
    <property type="old"/>
</html>

Alle Lösungen funktionieren nicht für das obige XML.

Die mögliche Lösung ist wie:

<?xml version="1.0"?> 

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

  <xsl:output omit-xml-declaration="yes" indent="yes"/>
  <xsl:template match="node()[local-name()='property']/@*[local-name()='type']">
      <xsl:attribute name="{name()}" namespace="{namespace-uri()}">
                some new value here
          </xsl:attribute>
  </xsl:template>

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

Sie benötigen eine Vorlage, die mit Ihrem Zielattribut übereinstimmt, und sonst nichts.

<xsl:template match='XPath/@myAttr'>
  <xsl:attribute name='myAttr'>This is the value</xsl:attribute>
</xsl:template>

Dies gilt zusätzlich zu dem "All", den Sie bereits haben (und ist in XSLT standardmäßig immer vorhanden). Eine spezifischere Übereinstimmung wird in Präferenz verwendet.

Ich hatte einen ähnlichen Fall, in dem ich ein Attribut aus einem einfachen Knoten löschen wollte, und konnte nicht herausfinden, welche Achse mich den Attributnamen lesen lassen würde. Am Ende musste ich nur benutzen

@*[name(.)!='AttributeNameToDelete']

Für die folgenden XML:

<?xml version="1.0" encoding="utf-8"?>
<root>
    <property type="foo"/>
    <node id="1"/>
    <property type="bar">
        <sub-property/>
    </property>
</root>

Ich konnte es mit dem folgenden XSLT arbeiten lassen:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="//property">
        <xsl:copy>
            <xsl:attribute name="type">
                <xsl:value-of select="@type"/>
                <xsl:text>-added</xsl:text>
            </xsl:attribute>
            <xsl:copy-of select="child::*"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

Wenn Ihr Quell -XML -Dokument einen eigenen Namespace hat, müssen Sie den Namespace in Ihrem Stylesheet deklarieren, ihm ein Präfix zuweisen und dieses Präfix verwenden, wenn Sie sich auf die Elemente der Quelle XML beziehen - z. B.:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xhtml="http://www.w3.org/1999/xhtml">

<xsl:output method="xml" encoding="utf-8" indent="yes" omit-xml-declaration="yes" />

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

<!-- exception-->    
<xsl:template match="xhtml:property/@type">
    <xsl:attribute name="type">
        <xsl:text>some new value</xsl:text> 
    </xsl:attribute>
</xsl:template>

</xsl:stylesheet>

Oder, wenn Sie es vorziehen:

...
<!-- exception-->    
<xsl:template match="@type[parent::xhtml:property]">
  <xsl:attribute name="type">
        <xsl:text>some new value</xsl:text> 
  </xsl:attribute>
</xsl:template>
...

Addendum: In dem sehr unwahrscheinlichen Fall, in dem der XML -Namespace vorher nicht bekannt ist, können Sie dies tun:

<?xml version="1.0" encoding="UTF-8"?>
<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" />

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

<!-- exception -->
<xsl:template match="*[local-name()='property']/@type">
    <xsl:attribute name="type">
        <xsl:text>some new value</xsl:text> 
    </xsl:attribute>
</xsl:template>

Natürlich ist es sehr schwierig, sich ein Szenario vorzustellen, in dem Sie im Voraus wissen würden, dass das Quell -XML -Dokument ein Element mit dem Namen "Eigenschaft" enthält, mit einem Attribut "Typ", das ersetzt werden muss - aber den Namespace des Dokuments immer noch nicht kennen. Ich habe dies hauptsächlich hinzugefügt, um zu zeigen, wie Ihre eigene Lösung optimiert werden kann.

Ich bin auch auf das gleiche Problem gestoßen und habe es wie folgt gelöst:

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

<!-- copy property element while only changing its type attribute -->
<xsl:template match="property">
  <xsl:copy>
    <xsl:attribute name="type">
      <xsl:value-of select="'your value here'"/>
    </xsl:attribute>
    <xsl:apply-templates select="@*[not(local-name()='type')]|node()"/>
  <xsl:copy>
</xsl:template>
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top