سؤال

لدي وثيقة XML ، وأريد تغيير القيم لأحد السمات.

أولاً ، قمت بنسخ كل شيء من المدخلات إلى الإخراج باستخدام:

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

والآن أريد تغيير قيمة السمة "type" في أي عنصر يدعى "property".

هل كانت مفيدة؟

المحلول

تم اختباره على مثال بسيط ، يعمل بشكل جيد:

<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>

تم تحريره لتشمل اقتراح Tomalak.

نصائح أخرى

هذه المشكلة لها حل كلاسيكي: باستخدام وتجاوز ال قالب الهوية هي واحدة من أنماط تصميم XSLT الأساسية وقوية:

<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>

عند تطبيقه على مستند XML هذا:

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

يتم إنتاج النتيجة المطلوبة:

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

لن تعمل الإجابات العليا إذا كان هناك تعريف XMLNS في عنصر الجذر:

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

جميع الحلول لن تعمل من أجل XML أعلاه.

الحل المحتمل مثل:

<?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>

تحتاج إلى قالب يتوافق مع سمة الهدف ، ولا شيء آخر.

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

هذا بالإضافة إلى "نسخة الكل" التي لديك بالفعل (وهي موجودة دائمًا افتراضيًا في XSLT). وجود تطابق أكثر تحديدا سيتم استخدامه في التفضيل.

كان لدي حالة مماثلة حيث أردت حذف سمة واحدة من عقدة بسيطة ، ولم أتمكن من معرفة المحور الذي سيسمح لي بقراءة اسم السمة. في النهاية ، كل ما كان علي فعله هو استخدام

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

ل XML التالي:

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

تمكنت من الحصول عليها للعمل مع XSLT التالية:

<?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>

إذا كان وثيقة XML الخاصة بمصدرك تحتوي على مساحة اسمها الخاصة ، فأنت بحاجة إلى إعلان مساحة الاسم في ورقة الأنماط الخاصة بك ، وتعيينه ببادئة ، واستخدم هذه البادئة عند الإشارة إلى عناصر المصدر XML - على سبيل المثال: على سبيل المثال:

<?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>

أو ، إذا كنت تفضل:

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

إضافة: في الحالة غير المرجح للغاية حيث لا تعرف مساحة اسم XML مسبقًا ، يمكنك القيام بذلك:

<?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>

بالطبع ، من الصعب للغاية تخيل سيناريو حيث تعرف مقدمًا أن مستند المصدر XML يحتوي على عنصر يسمى "خاصية" ، مع سمة تسمى "النوع" تحتاج إلى استبدال - ولكن لا تزال لا تعرف مساحة المستند. لقد أضفت ذلك بشكل أساسي لإظهار كيف يمكن تبسيط الحل الخاص بك.

صادفت أيضًا نفس المشكلة وحلتها على النحو التالي:

<!-- 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>
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top