سؤال

لديّ سلسلة في عقدة وأود تقسيم السلسلة على "؟" وإعادة العنصر الأخير في الصفيف.

على سبيل المثال، في الكتلة أدناه:

<a>
    <xsl:attribute name="href">
        /newpage.aspx?<xsl:value-of select="someNode"/>
    </xsl:attribute>
    Link text
</a>

أرغب في تقسيم someNode قيمة.

يحرر:إليك VB.Net الذي أستخدمه لتحميل Xsl لصفحة Asp.Net الخاصة بي:

Dim xslDocPath As String = HttpContext.Current.Server.MapPath("~/App_Data/someXslt.xsl")
Dim myXsltSettings As New XsltSettings()
Dim myXMLResolver As New XmlUrlResolver()

myXsltSettings.EnableScript = True
myXsltSettings.EnableDocumentFunction = True

myXslDoc = New XslCompiledTransform(False)
myXslDoc.Load(xslDocPath, myXsltSettings, myXMLResolver)

Dim myStringBuilder As New StringBuilder()
Dim myXmlWriter As XmlWriter = Nothing

Dim myXmlWriterSettings As New XmlWriterSettings()
myXmlWriterSettings.ConformanceLevel = ConformanceLevel.Auto
myXmlWriterSettings.Indent = True
myXmlWriterSettings.OmitXmlDeclaration = True

myXmlWriter = XmlWriter.Create(myStringBuilder, myXmlWriterSettings)

myXslDoc.Transform(xmlDoc, argumentList, myXmlWriter)

Return myStringBuilder.ToString()

تحديث: هنا مثال على تقسيم XML على عقدة معينة

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

المحلول

استخدم الطريقة العودية:

<xsl:template name="output-tokens">
    <xsl:param name="list" /> 
    <xsl:variable name="newlist" select="concat(normalize-space($list), ' ')" /> 
    <xsl:variable name="first" select="substring-before($newlist, ' ')" /> 
    <xsl:variable name="remaining" select="substring-after($newlist, ' ')" /> 
    <id>
        <xsl:value-of select="$first" /> 
    </id>
    <xsl:if test="$remaining">
        <xsl:call-template name="output-tokens">
            <xsl:with-param name="list" select="$remaining" /> 
        </xsl:call-template>
    </xsl:if>
</xsl:template>

نصائح أخرى

إذا كان بإمكانك استخدام XSLT 2.0 أو أعلى، فيمكنك استخدام tokenize(string, separator):

tokenize("XPath is fun", "\s+")
Result: ("XPath", "is", "fun")

انظر مرجع وظيفة w3schools XPath.

بشكل افتراضي، لا يدعم .NET XSLT 2.0، ناهيك عن XSLT 3.0.المعالجات 2.0+ المعروفة الوحيدة لـ .NET هي الساكسونية ل.NET مع آيكفم, اكسيلت, ومعالج .NET XSLT 3.0 حاليًا في مرحلة تجريبية، و XMLPrime معالج XSLT 2.0.

انتهى بي الأمر باستخدام substring-after() وظيفة.إليك ما نجح بالنسبة لي:

<a>
    <xsl:attribute name="href">
        /newpage.aspx?<xsl:value-of select="substring-after(someNode, '?')"/>
    </xsl:attribute>
    Link text
</a>

حتى بعد ضبط إصدار XSLT الخاص بي على 2.0، مازلت أحصل على "'tokenize()' is an unknown XSLT function."خطأ عند محاولة الاستخدام tokenize().

إضافة إمكانية أخرى، إذا كان محرك القالب الخاص بك يدعم ممتاز, ، ثم يمكنك استخدام رمز مميز () من ذاك.

على سبيل المثال:

<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:str="http://exslt.org/strings"
                extension-element-prefixes="str">

...
  <a>
    <xsl:attribute name="href">
      <xsl:text>/newpage.aspx?</xsl:text>
      <xsl:value-of select="str:tokenize(someNode)[2]"/>
    </xsl:attribute>              
  </a>
...
</xsl:stylesheet>

.NET لا يدعم XSLT 2.0، للأسف.أنا متأكد من أنه يدعم EXSLT، الذي يحتوي على ملف ينقسم() وظيفة.مايكروسوفت لديها الصفحة الأقدم بشأن تنفيذ EXSLT.

يمكنك كتابة قالب باستخدام string-before و string-after وظائف واستخدامها عبر.كتبت أ مدونة على هذا.

أخيرًا توصلت إلى قالب xslt الذي من شأنه تقسيم سلسلة محددة إلى سلاسل فرعية.لا أدعي أنه البرنامج النصي الأذكى، لكنه بالتأكيد يحل مشكلتي.

ورقة الأنماط:

<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:for-each select="Paths/Item">
<xsl:call-template name="SplitText">
<xsl:with-param name="inputString" select="Path"/>
<xsl:with-param name="delimiter" select="Delimiter"/>
</xsl:call-template>
<br/>
</xsl:for-each>
</xsl:template>
<xsl:template name="SplitText">
<xsl:param name="inputString"/>
<xsl:param name="delimiter"/>
<xsl:choose>
<xsl:when test="contains($inputString, $delimiter)">
<xsl:value-of select="substring-before($inputString,$delimiter)"/>
<xsl:text disable-output-escaping = "no"> </xsl:text>
<xsl:call-template name="SplitText">
<xsl:with-param name="inputString" select="substring-after($inputString,$delimiter)"/>
<xsl:with-param name="delimiter" select="$delimiter"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:choose>
<xsl:when test="$inputString = ''">
<xsl:text></xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$inputString"/>
<xsl:text> </xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>

ملف XML (الذي سيتم تحويله):

<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="textSpliter.xslt"?>
<Paths>
  <Item>
    <Path>C:\ProgramFiles\SomeWierdSoftware</Path>
    <Delimiter>\</Delimiter>
  </Item>
</Paths> 

لا يحتوي XSLT 1.0 على وظيفة تقسيم في حد ذاتها، ولكن من المحتمل أن تحقق ما تحاول القيام به باستخدام وظائف السلسلة الفرعية قبل والسلسلة الفرعية بعد.

وبدلاً من ذلك، إذا كنت تستخدم محرك Microsoft XSLT، فيمكنك استخدام لغة C# المضمنة.

للعلم فقط، إذا كنت تفعل ذلك باستخدام الإصدار 1.0، وتحتاج حقًا إلى تقسيم/رمز مميز، فأنت بحاجة إلى ملحقات xslt.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top