سؤال

تخيل أن لدي ملف XML التالي:

<a>قبل<b>الوسط</b>بعد</a>

أريد تحويله إلى شيء مثل هذا:

<a>قبل المنتصف بعد</a>

بمعنى آخر، أريد الحصول على جميع العقد الفرعية لعقدة معينة، ونقلها إلى العقدة الأصلية بالترتيب.هذا مثل تنفيذ هذا الأمر:"mv ./directory/* ."، ولكن لعقد XML.

أرغب في القيام بذلك باستخدام أدوات سطر أوامر يونكس.لقد كنت أحاول باستخدام xmlstarlet، وهو معالج قوي لـ XML لسطر الأوامر.حاولت أن أفعل شيئا مثل هذا، لكنه لا يعمل

صدى " u003Ca>قبل u003Cb>الوسطu003C/b> بعدu003C/a> " | xmlstarlet ed -m "// b/*" ".."

تحديث:تعتبر قوالب XSLT جيدة، حيث يمكن استدعاؤها من سطر الأوامر.

هدفي هنا هو "إزالة الروابط من صفحة XHTML"، أي استبدال مكان الرابط بمحتويات علامة الرابط.

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

المحلول

إذا كان هدفك الفعلي هو إزالة الروابط من صفحة الويب، فيجب عليك استخدام ورقة أنماط مثل هذه، والتي تتطابق مع جميع XHTML <a> العناصر (أفترض أنك تستخدم XHTML؟) وتقوم ببساطة بتطبيق القوالب على محتواها:

<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:h="http://www.w3.org/1999/xhtml"
  exclude-result-prefixes="h">

<!-- Don't copy the <a> elements, just process their content -->
<xsl:template match="h:a">
  <xsl:apply-templates />
</xsl:template>

<!-- identity template; copies everything by default -->
<xsl:template match="node()|@*">
  <xsl:copy>
    <xsl:apply-templates select="@*|node()" />
  </xsl:copy>
</xsl:template>

</xsl:stylesheet>

ستتعامل ورقة الأنماط هذه مع الموقف الذي يكون فيه لديك شيء متداخل داخل ال <a> العنصر الذي تريد الاحتفاظ به، مثل:

<p>Here is <a href="....">some <em>linked</em> text</a>.</p>

والتي سوف تريد أن تخرج على النحو التالي:

<p>Here is some <em>linked</em> text.</p>

وسوف يتعامل مع الموقف الذي يكون فيه الرابط متداخلاً داخل عنصر غير متوقع بين الأصل المعتاد (ملف <p> العنصر) و <a> العنصر، مثل:

<p>Here is <em>some <a href="...">linked</a> text</em>.</p>

نصائح أخرى

مثال لملف الإدخال (test.xml):

<?xml version="1.0" encoding="UTF-8"?>
<test>
<x>before<y>middle</y>after</x>
<a>before<b>middle</b>after</a>
<a>before<b>middle</b>after</a>
<x>before<y>middle</y>after</x>
<a>before<b>middle</b>after</a>
<embedded>foo<a>before<b>middle</b>after</a>bar</embedded>
</test>

ورقة أنماط XSLT (collapse.xsl:

    <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="a">
        <xsl:copy>
          <xsl:value-of select="."/>
        </xsl:copy>
      </xsl:template>

    </xsl:stylesheet>

قم بالتشغيل باستخدام XmlStarlet

xml tr collapse.xsl test.xml

ينتج عنه:

<?xml version="1.0"?>
<test>
<x>before<y>middle</y>after</x>
<a>beforemiddleafter</a>
<a>beforemiddleafter</a>
<x>before<y>middle</y>after</x>
<a>beforemiddleafter</a>
<embedded>foo<a>beforemiddleafter</a>bar</embedded>
</test>

القالب الأول في ورقة الأنماط هو تحويل الهوية الأساسي (فقط قم بنسخ مستند XML المدخل بالكامل).يطابق القالب الثاني على وجه التحديد العناصر التي تريد "طيها" ويقوم فقط بنسخ العلامات وإدراج قيمة السلسلة للعنصر (= تسلسل قيمة السلسلة للعقد التابعة).

في XSLT، يمكنك فقط كتابة:

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

<xsl:template match="a/b"><xsl:value-of select="."/></xsl:template>

وستحصل على:

<a>beforemiddleafter</a>

لذا، إذا أردت القيام بذلك بالطريقة السهلة، يمكنك فقط إنشاء ورقة أنماط XSL وتشغيل ملف XML الخاص بك من خلال ذلك.

أدرك أن هذا ليس ما قلت أنك ترغب في القيام به (باستخدام سطر أوامر Unix)، ولكن.أنا لا أعرف أي شيء عن يونكس، لذلك ربما يمكن لشخص آخر ملء الفراغات، على سبيل المثال.نوع من مكالمات سطر الأوامر التي يمكنها تنفيذ ما ورد أعلاه.

باستخدام xmlstarlet:

xmlstr='<a>before<b>middle</b>after</a>'
updatestr="$(echo "$xmlstr" | xmlstarlet sel -T -t -m "/a/b" -v '../.' -n | sed -n '1{p;q;}')"
echo "$xmlstr" | xmlstarlet ed -u "/a" -v "$updatestr"

هل جربت هذا؟

file.xml

<r>
    <a>start<b>middle</b>end</a>
</r>

template.xsl

<xsl:template match="/">
    <a><xsl:value-of select="r/a" /></a>
</xsl:template>

output

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